summaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /arch/alpha
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/Makefile23
-rw-r--r--arch/alpha/boot/bootp.c8
-rw-r--r--arch/alpha/boot/main.c2
-rw-r--r--arch/alpha/config.in19
-rw-r--r--arch/alpha/defconfig2
-rw-r--r--arch/alpha/kernel/Makefile25
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c5
-rw-r--r--arch/alpha/kernel/core_apecs.c4
-rw-r--r--arch/alpha/kernel/core_cia.c10
-rw-r--r--arch/alpha/kernel/core_irongate.c353
-rw-r--r--arch/alpha/kernel/core_lca.c4
-rw-r--r--arch/alpha/kernel/core_mcpcia.c146
-rw-r--r--arch/alpha/kernel/core_polaris.c6
-rw-r--r--arch/alpha/kernel/core_pyxis.c10
-rw-r--r--arch/alpha/kernel/core_t2.c4
-rw-r--r--arch/alpha/kernel/core_tsunami.c89
-rw-r--r--arch/alpha/kernel/irq.c128
-rw-r--r--arch/alpha/kernel/irq_impl.h49
-rw-r--r--arch/alpha/kernel/machvec_impl.h10
-rw-r--r--arch/alpha/kernel/pci.c209
-rw-r--r--arch/alpha/kernel/pci_impl.h5
-rw-r--r--arch/alpha/kernel/process.c73
-rw-r--r--arch/alpha/kernel/proto.h26
-rw-r--r--arch/alpha/kernel/ptrace.c6
-rw-r--r--arch/alpha/kernel/setup.c257
-rw-r--r--arch/alpha/kernel/signal.c1
-rw-r--r--arch/alpha/kernel/smp.c62
-rw-r--r--arch/alpha/kernel/sys_alcor.c6
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c8
-rw-r--r--arch/alpha/kernel/sys_dp264.c73
-rw-r--r--arch/alpha/kernel/sys_eb64p.c5
-rw-r--r--arch/alpha/kernel/sys_eiger.c215
-rw-r--r--arch/alpha/kernel/sys_jensen.c4
-rw-r--r--arch/alpha/kernel/sys_miata.c5
-rw-r--r--arch/alpha/kernel/sys_mikasa.c5
-rw-r--r--arch/alpha/kernel/sys_nautilus.c535
-rw-r--r--arch/alpha/kernel/sys_noritake.c5
-rw-r--r--arch/alpha/kernel/sys_rawhide.c109
-rw-r--r--arch/alpha/kernel/sys_ruffian.c7
-rw-r--r--arch/alpha/kernel/sys_rx164.c4
-rw-r--r--arch/alpha/kernel/sys_sable.c5
-rw-r--r--arch/alpha/kernel/sys_sio.c20
-rw-r--r--arch/alpha/kernel/sys_sx164.c4
-rw-r--r--arch/alpha/kernel/sys_takara.c72
-rw-r--r--arch/alpha/kernel/time.c23
-rw-r--r--arch/alpha/kernel/traps.c2
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/fpreg.c (renamed from arch/alpha/kernel/fpreg.c)95
-rw-r--r--arch/alpha/lib/io.c28
-rw-r--r--arch/alpha/math-emu/Makefile10
-rw-r--r--arch/alpha/math-emu/fp-emul.c354
-rw-r--r--arch/alpha/math-emu/fp-emul.h10
-rw-r--r--arch/alpha/math-emu/ieee-math.c1382
-rw-r--r--arch/alpha/math-emu/ieee-math.h54
-rw-r--r--arch/alpha/math-emu/math.c447
-rw-r--r--arch/alpha/math-emu/sfp-util.h40
-rw-r--r--arch/alpha/mm/fault.c2
-rw-r--r--arch/alpha/mm/init.c196
58 files changed, 2748 insertions, 2515 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 90013b3fb..28ba0dd51 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -59,27 +59,14 @@ ifeq ($(have_mcpu),y)
endif
# For TSUNAMI, we must have the assembler not emulate our instructions.
-# The same is true for POLARIS, and now PYXIS.
+# The same is true for IRONGATE, POLARIS, PYXIS.
# BWX is most important, but we don't really want any emulation ever.
+
ifeq ($(old_gas),y)
- ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS)$(CONFIG_ALPHA_PYXIS),)
- # How do we do #error in make?
- CFLAGS := --error-please-upgrade-your-assembler
- endif
-else
- ifeq ($(CONFIG_ALPHA_GENERIC),y)
- CFLAGS := $(CFLAGS) -Wa,-mev6
- endif
- ifeq ($(CONFIG_ALPHA_PYXIS),y)
- CFLAGS := $(CFLAGS) -Wa,-m21164a
- endif
- ifeq ($(CONFIG_ALPHA_POLARIS),y)
- CFLAGS := $(CFLAGS) -Wa,-m21164pc
- endif
- ifeq ($(CONFIG_ALPHA_TSUNAMI),y)
- CFLAGS := $(CFLAGS) -Wa,-mev6
- endif
+ # How do we do #error in make?
+ CFLAGS := --error-please-upgrade-your-assembler
endif
+CFLAGS := $(CFLAGS) -Wa,-mev6
HEAD := arch/alpha/kernel/head.o
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
index 90fccb766..bb892ba3c 100644
--- a/arch/alpha/boot/bootp.c
+++ b/arch/alpha/boot/bootp.c
@@ -200,11 +200,11 @@ start_kernel(void)
load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
- memset((char*)ZERO_PAGE(0), 0, PAGE_SIZE);
- strcpy((char*)ZERO_PAGE(0), envval);
+ memset((char*)ZERO_PGE, 0, PAGE_SIZE);
+ strcpy((char*)ZERO_PGE, envval);
#ifdef INITRD_SIZE
- ((long *)(ZERO_PAGE(0)+256))[0] = initrd_start;
- ((long *)(ZERO_PAGE(0)+256))[1] = INITRD_SIZE;
+ ((long *)(ZERO_PGE+256))[0] = initrd_start;
+ ((long *)(ZERO_PGE+256))[1] = INITRD_SIZE;
#endif
runkernel();
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c
index c97896e8b..07913d899 100644
--- a/arch/alpha/boot/main.c
+++ b/arch/alpha/boot/main.c
@@ -182,7 +182,7 @@ void start_kernel(void)
nbytes = 0;
}
envval[nbytes] = '\0';
- strcpy((char*)ZERO_PAGE(0), envval);
+ strcpy((char*)ZERO_PGE, envval);
srm_printk(" Ok\nNow booting the kernel\n");
runkernel();
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index f6dc93f61..35e9edeb0 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -33,10 +33,12 @@ choice 'Alpha system type' \
EB64+ CONFIG_ALPHA_EB64P \
EB66 CONFIG_ALPHA_EB66 \
EB66+ CONFIG_ALPHA_EB66P \
+ Eiger CONFIG_ALPHA_EIGER \
Jensen CONFIG_ALPHA_JENSEN \
LX164 CONFIG_ALPHA_LX164 \
Miata CONFIG_ALPHA_MIATA \
Mikasa CONFIG_ALPHA_MIKASA \
+ Nautilus CONFIG_ALPHA_NAUTILUS \
Noname CONFIG_ALPHA_NONAME \
Noritake CONFIG_ALPHA_NORITAKE \
PC164 CONFIG_ALPHA_PC164 \
@@ -54,6 +56,7 @@ unset CONFIG_PCI CONFIG_ALPHA_EISA
unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
+unset CONFIG_ALPHA_IRONGATE
if [ "$CONFIG_ALPHA_GENERIC" = "y" ]
then
@@ -117,7 +120,7 @@ then
define_bool CONFIG_ALPHA_EV5 y
define_bool CONFIG_ALPHA_PYXIS y
fi
-if [ "$CONFIG_ALPHA_DP264" = "y" ]
+if [ "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_EIGER" = "y" ]
then
define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_EV6 y
@@ -139,6 +142,12 @@ if [ "$CONFIG_ALPHA_JENSEN" = "y" ]
then
define_bool CONFIG_ALPHA_EV4 y
fi
+if [ "$CONFIG_ALPHA_NAUTILUS" = "y" ]
+then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_EV6 y
+ define_bool CONFIG_ALPHA_IRONGATE y
+fi
if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
-o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \
@@ -147,7 +156,8 @@ if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
-o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \
-o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \
-o "$CONFIG_ALPHA_LX164" = "y" -o "$CONFIG_ALPHA_SX164" = "y" \
- -o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" ]
+ -o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" \
+ -o "$CONFIG_ALPHA_EIGER" = "y" ]
then
bool 'Use SRM as bootloader' CONFIG_ALPHA_SRM
fi
@@ -168,6 +178,8 @@ then
bool 'Symmetric multi-processing support' CONFIG_SMP
fi
+source drivers/pci/Config.in
+
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -244,11 +256,10 @@ if [ "$CONFIG_VT" = "y" ]; then
mainmenu_option next_comment
comment 'Console drivers'
bool 'VGA text console' CONFIG_VGA_CONSOLE
- bool 'Support for frame buffer devices' CONFIG_FB
+ source drivers/video/Config.in
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_PCI_CONSOLE y
fi
- source drivers/video/Config.in
endmenu
fi
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 54a05ea5a..ba6f0070b 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -32,6 +32,7 @@ CONFIG_ALPHA_GENERIC=y
# CONFIG_ALPHA_LX164 is not set
# CONFIG_ALPHA_MIATA is not set
# CONFIG_ALPHA_MIKASA is not set
+# CONFIG_ALPHA_NAUTILUS is not set
# CONFIG_ALPHA_NONAME is not set
# CONFIG_ALPHA_NORITAKE is not set
# CONFIG_ALPHA_PC164 is not set
@@ -43,6 +44,7 @@ CONFIG_ALPHA_GENERIC=y
# CONFIG_ALPHA_SABLE is not set
# CONFIG_ALPHA_TAKARA is not set
CONFIG_PCI=y
+CONFIG_PCI_NAMES=y
# CONFIG_SMP is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 282147e72..9210ae57c 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -12,22 +12,20 @@
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
-all: kernel.o head.o
-
O_TARGET := kernel.o
O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
- ptrace.o time.o fpreg.o semaphore.o
+ ptrace.o time.o semaphore.o
OX_OBJS := alpha_ksyms.o
ifdef CONFIG_ALPHA_GENERIC
-O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \
- core_t2.o core_tsunami.o core_polaris.o \
- sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o \
- sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \
- sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \
- sys_sx164.o sys_takara.o sys_rx164.o \
+O_OBJS += core_apecs.o core_cia.o core_irongate.o core_lca.o core_mcpcia.o \
+ core_polaris.o core_pyxis.o core_t2.o core_tsunami.o \
+ sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
+ sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o \
+ sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
+ sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o \
es1888.o smc37c669.o smc37c93x.o ns87312.o pci.o
else
@@ -42,6 +40,9 @@ endif
ifdef CONFIG_ALPHA_CIA
O_OBJS += core_cia.o
endif
+ifdef CONFIG_ALPHA_IRONGATE
+O_OBJS += core_irongate.o
+endif
ifdef CONFIG_ALPHA_LCA
O_OBJS += core_lca.o
endif
@@ -74,6 +75,9 @@ endif
ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
O_OBJS += sys_eb64p.o
endif
+ifdef CONFIG_ALPHA_EIGER
+O_OBJS += sys_eiger.o
+endif
ifdef CONFIG_ALPHA_JENSEN
O_OBJS += sys_jensen.o
endif
@@ -83,6 +87,9 @@ endif
ifdef CONFIG_ALPHA_MIKASA
O_OBJS += sys_mikasa.o
endif
+ifdef CONFIG_ALPHA_NAUTILUS
+O_OBJS += sys_nautilus.o
+endif
ifdef CONFIG_ALPHA_NORITAKE
O_OBJS += sys_noritake.o
endif
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index ffd93ca9d..ef8be067c 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -27,7 +27,7 @@
#include <asm/fpu.h>
#include <asm/irq.h>
#include <asm/machvec.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/semaphore.h>
#define __KERNEL_SYSCALLS__
@@ -103,7 +103,9 @@ EXPORT_SYMBOL(hwrpb);
EXPORT_SYMBOL(wrusp);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(alpha_read_fp_reg);
+EXPORT_SYMBOL(alpha_read_fp_reg_s);
EXPORT_SYMBOL(alpha_write_fp_reg);
+EXPORT_SYMBOL(alpha_write_fp_reg_s);
/* In-kernel system calls. */
EXPORT_SYMBOL(kernel_thread);
@@ -123,6 +125,7 @@ EXPORT_SYMBOL(csum_tcpudp_magic);
EXPORT_SYMBOL(ip_compute_csum);
EXPORT_SYMBOL(ip_fast_csum);
EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
EXPORT_SYMBOL(csum_partial_copy_from_user);
EXPORT_SYMBOL(csum_ipv6_magic);
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
index 6a402a3e1..04e556f2e 100644
--- a/arch/alpha/kernel/core_apecs.c
+++ b/arch/alpha/kernel/core_apecs.c
@@ -357,7 +357,7 @@ struct pci_ops apecs_pci_ops =
};
void __init
-apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+apecs_init_arch(void)
{
struct pci_controler *hose;
@@ -386,7 +386,7 @@ apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
+ hose = alloc_pci_controler();
hose->io_space = &ioport_resource;
hose->mem_space = &iomem_resource;
hose->config_space = APECS_CONF;
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index 4e773862b..9f628bff6 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -315,7 +315,7 @@ struct pci_ops cia_pci_ops =
};
void __init
-cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+cia_init_arch(void)
{
struct pci_controler *hose;
struct resource *hae_mem;
@@ -424,8 +424,8 @@ cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
- hae_mem = alloc_resource(mem_start);
+ hose = alloc_pci_controler();
+ hae_mem = alloc_resource();
hose->io_space = &ioport_resource;
hose->mem_space = hae_mem;
@@ -435,8 +435,10 @@ cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
hae_mem->start = 0;
hae_mem->end = CIA_MEM_R1_MASK;
hae_mem->name = pci_hae0_name;
+ hae_mem->flags = IORESOURCE_MEM;
- request_resource(&iomem_resource, hae_mem);
+ if (request_resource(&iomem_resource, hae_mem) < 0)
+ printk(KERN_ERR "Failed to request HAE_MEM\n");
}
static inline void
diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
new file mode 100644
index 000000000..ef686277c
--- /dev/null
+++ b/arch/alpha/kernel/core_irongate.c
@@ -0,0 +1,353 @@
+/*
+ * linux/arch/alpha/kernel/core_irongate.c
+ *
+ * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
+ *
+ * Copyright (C) 1999 Alpha Processor, Inc.,
+ * (David Daniel, Stig Telfer, Soohoon Lee)
+ *
+ * Code common to all IRONGATE core logic chips.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/pci.h>
+#include <asm/hwrpb.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_irongate.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+#include "pci_impl.h"
+
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the I/O controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBG_CFG(args) printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address accordingly. It is therefore not safe
+ * to have concurrent invocations to configuration space access
+ * routines, but there really shouldn't be any need for this.
+ *
+ * addr[31:24] reserved
+ * addr[23:16] bus number (8 bits = 128 possible buses)
+ * addr[15:11] Device number (5 bits)
+ * addr[10: 8] function number
+ * addr[ 7: 2] register number
+ *
+ * For IRONGATE:
+ * if (bus = addr[23:16]) == 0
+ * then
+ * type 0 config cycle:
+ * addr_on_pci[31:11] = id selection for device = addr[15:11]
+ * addr_on_pci[10: 2] = addr[10: 2] ???
+ * addr_on_pci[ 1: 0] = 00
+ * else
+ * type 1 config cycle (pass on with no decoding):
+ * addr_on_pci[31:24] = 0
+ * addr_on_pci[23: 2] = addr[23: 2]
+ * addr_on_pci[ 1: 0] = 01
+ * fi
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., SCSI and Ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+
+static int
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ unsigned long addr;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
+
+ DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
+ "pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
+
+ *type1 = (bus != 0);
+
+ addr = (bus << 16) | (device_fn << 8) | where;
+ addr |= IRONGATE_CONF;
+
+ *pci_addr = addr;
+ DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+static int
+irongate_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(dev, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldbu(*(vucp)addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+irongate_read_config_word(struct pci_dev *dev, int where, u16 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(dev, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldwu(*(vusp)addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+irongate_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(dev, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = *(vuip)addr;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+irongate_write_config_byte(struct pci_dev *dev, int where, u8 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(dev, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stb(value, *(vucp)addr);
+ mb();
+ __kernel_ldbu(*(vucp)addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+irongate_write_config_word(struct pci_dev *dev, int where, u16 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(dev, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stw(value, *(vusp)addr);
+ mb();
+ __kernel_ldwu(*(vusp)addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+irongate_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(dev, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *(vuip)addr = value;
+ mb();
+ *(vuip)addr;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+struct pci_ops irongate_pci_ops =
+{
+ read_byte: irongate_read_config_byte,
+ read_word: irongate_read_config_word,
+ read_dword: irongate_read_config_dword,
+ write_byte: irongate_write_config_byte,
+ write_word: irongate_write_config_word,
+ write_dword: irongate_write_config_dword
+};
+
+#if 0
+static void
+irongate_register_dump(const char *function_name)
+{
+ printk("%s: Irongate registers:\n"
+ "\tdev_vendor\t0x%08x\n"
+ "\tstat_cmd\t0x%08x\n"
+ "\tclass\t\t0x%08x\n"
+ "\tlatency\t\t0x%08x\n"
+ "\tbar0\t\t0x%08x\n"
+ "\tbar1\t\t0x%08x\n"
+ "\tbar2\t\t0x%08x\n"
+ "\trsrvd0[0]\t0x%08x\n"
+ "\trsrvd0[1]\t0x%08x\n"
+ "\trsrvd0[2]\t0x%08x\n"
+ "\trsrvd0[3]\t0x%08x\n"
+ "\trsrvd0[4]\t0x%08x\n"
+ "\trsrvd0[5]\t0x%08x\n"
+ "\tcapptr\t\t0x%08x\n"
+ "\trsrvd1[0]\t0x%08x\n"
+ "\trsrvd1[1]\t0x%08x\n"
+ "\tbacsr10\t\t0x%08x\n"
+ "\tbacsr32\t\t0x%08x\n"
+ "\tbacsr54\t\t0x%08x\n"
+ "\trsrvd2[0]\t0x%08x\n"
+ "\tdrammap\t\t0x%08x\n"
+ "\tdramtm\t\t0x%08x\n"
+ "\tdramms\t\t0x%08x\n"
+ "\trsrvd3[0]\t0x%08x\n"
+ "\tbiu0\t\t0x%08x\n"
+ "\tbiusip\t\t0x%08x\n"
+ "\trsrvd4[0]\t0x%08x\n"
+ "\trsrvd4[1]\t0x%08x\n"
+ "\tmro\t\t0x%08x\n"
+ "\trsrvd5[0]\t0x%08x\n"
+ "\trsrvd5[1]\t0x%08x\n"
+ "\trsrvd5[2]\t0x%08x\n"
+ "\twhami\t\t0x%08x\n"
+ "\tpciarb\t\t0x%08x\n"
+ "\tpcicfg\t\t0x%08x\n"
+ "\trsrvd6[0]\t0x%08x\n"
+ "\trsrvd6[1]\t0x%08x\n"
+ "\trsrvd6[2]\t0x%08x\n"
+ "\trsrvd6[3]\t0x%08x\n"
+ "\trsrvd6[4]\t0x%08x\n"
+ "\tagpcap\t\t0x%08x\n"
+ "\tagpstat\t\t0x%08x\n"
+ "\tagpcmd\t\t0x%08x\n"
+ "\tagpva\t\t0x%08x\n"
+ "\tagpmode\t\t0x%08x\n",
+ function_name,
+ IRONGATE0->dev_vendor,
+ IRONGATE0->stat_cmd,
+ IRONGATE0->class,
+ IRONGATE0->latency,
+ IRONGATE0->bar0,
+ IRONGATE0->bar1,
+ IRONGATE0->bar2,
+ IRONGATE0->rsrvd0[0],
+ IRONGATE0->rsrvd0[1],
+ IRONGATE0->rsrvd0[2],
+ IRONGATE0->rsrvd0[3],
+ IRONGATE0->rsrvd0[4],
+ IRONGATE0->rsrvd0[5],
+ IRONGATE0->capptr,
+ IRONGATE0->rsrvd1[0],
+ IRONGATE0->rsrvd1[1],
+ IRONGATE0->bacsr10,
+ IRONGATE0->bacsr32,
+ IRONGATE0->bacsr54,
+ IRONGATE0->rsrvd2[0],
+ IRONGATE0->drammap,
+ IRONGATE0->dramtm,
+ IRONGATE0->dramms,
+ IRONGATE0->rsrvd3[0],
+ IRONGATE0->biu0,
+ IRONGATE0->biusip,
+ IRONGATE0->rsrvd4[0],
+ IRONGATE0->rsrvd4[1],
+ IRONGATE0->mro,
+ IRONGATE0->rsrvd5[0],
+ IRONGATE0->rsrvd5[1],
+ IRONGATE0->rsrvd5[2],
+ IRONGATE0->whami,
+ IRONGATE0->pciarb,
+ IRONGATE0->pcicfg,
+ IRONGATE0->rsrvd6[0],
+ IRONGATE0->rsrvd6[1],
+ IRONGATE0->rsrvd6[2],
+ IRONGATE0->rsrvd6[3],
+ IRONGATE0->rsrvd6[4],
+ IRONGATE0->agpcap,
+ IRONGATE0->agpstat,
+ IRONGATE0->agpcmd,
+ IRONGATE0->agpva,
+ IRONGATE0->agpmode);
+}
+#else
+#define irongate_register_dump(x)
+#endif
+
+int
+irongate_pci_clr_err(void)
+{
+ unsigned int nmi_ctl=0;
+ unsigned int IRONGATE_jd;
+
+again:
+ IRONGATE_jd = IRONGATE0->stat_cmd;
+ printk("Iron stat_cmd %x\n", IRONGATE_jd);
+ IRONGATE0->stat_cmd = IRONGATE_jd; /* write again clears error bits */
+ mb();
+ IRONGATE_jd = IRONGATE0->stat_cmd; /* re-read to force write */
+
+ IRONGATE_jd = IRONGATE0->dramms;
+ printk("Iron dramms %x\n", IRONGATE_jd);
+ IRONGATE0->dramms = IRONGATE_jd; /* write again clears error bits */
+ mb();
+ IRONGATE_jd = IRONGATE0->dramms; /* re-read to force write */
+
+ /* Clear ALI NMI */
+ nmi_ctl = inb(0x61);
+ nmi_ctl |= 0x0c;
+ outb(nmi_ctl, 0x61);
+ nmi_ctl &= ~0x0c;
+ outb(nmi_ctl, 0x61);
+
+ IRONGATE_jd = IRONGATE0->dramms;
+ if (IRONGATE_jd & 0x300) goto again;
+
+ return 0;
+}
+
+void __init
+irongate_init_arch(void)
+{
+ struct pci_controler *hose;
+
+ irongate_pci_clr_err();
+ irongate_register_dump(__FUNCTION__);
+
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler();
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = IRONGATE_CONF;
+ hose->index = 0;
+}
diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c
index 8b87f8afa..266023f77 100644
--- a/arch/alpha/kernel/core_lca.c
+++ b/arch/alpha/kernel/core_lca.c
@@ -279,7 +279,7 @@ struct pci_ops lca_pci_ops =
};
void __init
-lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+lca_init_arch(void)
{
struct pci_controler *hose;
@@ -307,7 +307,7 @@ lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
+ hose = alloc_pci_controler();
hose->io_space = &ioport_resource;
hose->mem_space = &iomem_resource;
hose->config_space = LCA_CONF;
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
index 1222556d3..b4fe28849 100644
--- a/arch/alpha/kernel/core_mcpcia.c
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -43,7 +43,7 @@
# define DBG_CFG(args)
#endif
-#define MCPCIA_MAX_HOSES 2
+#define MCPCIA_MAX_HOSES 4
/* Dodge has PCI0 and PCI1 at MID 4 and 5 respectively. Durango adds
PCI2 and PCI3 at MID 6 and 7 respectively. */
@@ -205,7 +205,7 @@ mk_conf_addr(struct pci_dev *dev, int where, struct pci_controler *hose,
static int
mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ struct pci_controler *hose = dev->sysdata;
unsigned long addr, w;
unsigned char type1;
@@ -221,7 +221,7 @@ mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
static int
mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ struct pci_controler *hose = dev->sysdata;
unsigned long addr, w;
unsigned char type1;
@@ -237,7 +237,7 @@ mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value)
static int
mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ struct pci_controler *hose = dev->sysdata;
unsigned long addr;
unsigned char type1;
@@ -252,7 +252,7 @@ mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
static int
mcpcia_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ struct pci_controler *hose = dev->sysdata;
unsigned long addr;
unsigned char type1;
@@ -305,6 +305,7 @@ mcpcia_probe_hose(int h)
mb();
mb();
draina();
+ wrmces(7);
mcheck_expected(cpu) = 1;
mcheck_taken(cpu) = 0;
mcheck_extra(cpu) = mid;
@@ -327,16 +328,16 @@ mcpcia_probe_hose(int h)
}
static void __init
-mcpcia_new_hose(unsigned long *mem_start, int h)
+mcpcia_new_hose(int h)
{
struct pci_controler *hose;
struct resource *io, *mem, *hae_mem;
int mid = hose2mid(h);
- hose = alloc_pci_controler(mem_start);
- io = alloc_resource(mem_start);
- mem = alloc_resource(mem_start);
- hae_mem = alloc_resource(mem_start);
+ hose = alloc_pci_controler();
+ io = alloc_resource();
+ mem = alloc_resource();
+ hae_mem = alloc_resource();
hose->io_space = io;
hose->mem_space = hae_mem;
@@ -346,18 +347,33 @@ mcpcia_new_hose(unsigned long *mem_start, int h)
io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS;
io->end = io->start + 0xffff;
io->name = pci_io_names[h];
+ io->flags = IORESOURCE_IO;
mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS;
mem->end = mem->start + 0xffffffff;
mem->name = pci_mem_names[h];
+ mem->flags = IORESOURCE_MEM;
hae_mem->start = mem->start;
hae_mem->end = mem->start + MCPCIA_MEM_MASK;
hae_mem->name = pci_hae0_name;
+ hae_mem->flags = IORESOURCE_MEM;
+
+ if (request_resource(&ioport_resource, io) < 0)
+ printk(KERN_ERR "Failed to request IO on hose %d\n", h);
+ if (request_resource(&iomem_resource, mem) < 0)
+ printk(KERN_ERR "Failed to request MEM on hose %d\n", h);
+ if (request_resource(mem, hae_mem) < 0)
+ printk(KERN_ERR "Failed to request HAE_MEM on hose %d\n", h);
+}
- request_resource(&ioport_resource, io);
- request_resource(&iomem_resource, mem);
- request_resource(mem, hae_mem);
+static void
+mcpcia_pci_clr_err(int mid)
+{
+ *(vuip)MCPCIA_CAP_ERR(mid);
+ *(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff; /* Clear them all. */
+ mb();
+ *(vuip)MCPCIA_CAP_ERR(mid); /* Re-read for force write. */
}
static void __init
@@ -366,19 +382,13 @@ mcpcia_startup_hose(struct pci_controler *hose)
int mid = hose2mid(hose->index);
unsigned int tmp;
+ mcpcia_pci_clr_err(mid);
+
/*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ * Set up error reporting.
*/
-#if 0
- tmp = *(vuip)MCPCIA_ERR_MASK(mid);
- tmp &= ~4;
- *(vuip)MCPCIA_ERR_MASK(mid) = tmp;
- mb();
- tmp = *(vuip)MCPCIA_ERR_MASK(mid);
-#endif
-
tmp = *(vuip)MCPCIA_CAP_ERR(mid);
- tmp |= 0x0006; /* master/target abort */
+ tmp |= 0x0006; /* master/target abort */
*(vuip)MCPCIA_CAP_ERR(mid) = tmp;
mb();
tmp = *(vuip)MCPCIA_CAP_ERR(mid);
@@ -420,29 +430,39 @@ mcpcia_startup_hose(struct pci_controler *hose)
}
void __init
-mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+mcpcia_init_arch(void)
{
- extern asmlinkage void entInt(void);
- struct pci_controler *hose;
- int h, hose_count = 0;
-
- /* Ho hum.. init_arch is called before init_IRQ, but we need to be
- able to handle machine checks. So install the handler now. */
- wrent(entInt, 0);
-
/* With multiple PCI busses, we play with I/O as physical addrs. */
ioport_resource.end = ~0UL;
iomem_resource.end = ~0UL;
+ /* Allocate hose 0. That's the one that all the ISA junk hangs
+ off of, from which we'll be registering stuff here in a bit.
+ Other hose detection is done in mcpcia_init_hoses, which is
+ called from init_IRQ. */
+
+ mcpcia_new_hose(0);
+}
+
+/* This is called from init_IRQ, since we cannot take interrupts
+ before then. Which means we cannot do this in init_arch. */
+
+void __init
+mcpcia_init_hoses(void)
+{
+ struct pci_controler *hose;
+ int h, hose_count = 0;
+
/* First, find how many hoses we have. */
for (h = 0; h < MCPCIA_MAX_HOSES; ++h) {
if (mcpcia_probe_hose(h)) {
- mcpcia_new_hose(mem_start, h);
+ if (h != 0)
+ mcpcia_new_hose(h);
hose_count++;
}
}
- printk("mcpcia_init_arch: found %d hoses\n", hose_count);
+ printk("mcpcia_init_hoses: found %d hoses\n", hose_count);
/* Now do init for each hose. */
for (hose = hose_head; hose; hose = hose->next)
@@ -450,15 +470,6 @@ mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
}
static void
-mcpcia_pci_clr_err(int mid)
-{
- *(vuip)MCPCIA_CAP_ERR(mid);
- *(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff; /* Clear them all. */
- mb();
- *(vuip)MCPCIA_CAP_ERR(mid); /* Re-read for force write. */
-}
-
-static void
mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
{
struct el_common_EV5_uncorrectable_mcheck *frame;
@@ -468,65 +479,65 @@ mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
/* Print PAL fields */
for (i = 0; i < 24; i += 2) {
- printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r",
+ printk(" paltmp[%d-%d] = %16lx %16lx\n",
i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
}
for (i = 0; i < 8; i += 2) {
- printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r",
+ printk(" shadow[%d-%d] = %16lx %16lx\n",
i, i+1, frame->shadow[i],
frame->shadow[i+1]);
}
- printk("\tAddr of excepting instruction\t= %16lx\n\r",
+ printk(" Addr of excepting instruction = %16lx\n",
frame->exc_addr);
- printk("\tSummary of arithmetic traps\t= %16lx\n\r",
+ printk(" Summary of arithmetic traps = %16lx\n",
frame->exc_sum);
- printk("\tException mask\t\t\t= %16lx\n\r",
+ printk(" Exception mask = %16lx\n",
frame->exc_mask);
- printk("\tBase address for PALcode\t= %16lx\n\r",
+ printk(" Base address for PALcode = %16lx\n",
frame->pal_base);
- printk("\tInterrupt Status Reg\t\t= %16lx\n\r",
+ printk(" Interrupt Status Reg = %16lx\n",
frame->isr);
- printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r",
+ printk(" CURRENT SETUP OF EV5 IBOX = %16lx\n",
frame->icsr);
- printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r",
+ printk(" I-CACHE Reg %s parity error = %16lx\n",
(frame->ic_perr_stat & 0x800L) ?
"Data" : "Tag",
frame->ic_perr_stat);
- printk("\tD-CACHE error Reg\t\t= %16lx\n\r",
+ printk(" D-CACHE error Reg = %16lx\n",
frame->dc_perr_stat);
if (frame->dc_perr_stat & 0x2) {
switch (frame->dc_perr_stat & 0x03c) {
case 8:
- printk("\t\tData error in bank 1\n\r");
+ printk(" Data error in bank 1\n");
break;
case 4:
- printk("\t\tData error in bank 0\n\r");
+ printk(" Data error in bank 0\n");
break;
case 20:
- printk("\t\tTag error in bank 1\n\r");
+ printk(" Tag error in bank 1\n");
break;
case 10:
- printk("\t\tTag error in bank 0\n\r");
+ printk(" Tag error in bank 0\n");
break;
}
}
- printk("\tEffective VA\t\t\t= %16lx\n\r",
+ printk(" Effective VA = %16lx\n",
frame->va);
- printk("\tReason for D-stream\t\t= %16lx\n\r",
+ printk(" Reason for D-stream = %16lx\n",
frame->mm_stat);
- printk("\tEV5 SCache address\t\t= %16lx\n\r",
+ printk(" EV5 SCache address = %16lx\n",
frame->sc_addr);
- printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r",
+ printk(" EV5 SCache TAG/Data parity = %16lx\n",
frame->sc_stat);
- printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r",
+ printk(" EV5 BC_TAG_ADDR = %16lx\n",
frame->bc_tag_addr);
- printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r",
+ printk(" EV5 EI_ADDR: Phys addr of Xfer = %16lx\n",
frame->ei_addr);
- printk("\tFill Syndrome\t\t\t= %16lx\n\r",
+ printk(" Fill Syndrome = %16lx\n",
frame->fill_syndrome);
- printk("\tEI_STAT reg\t\t\t= %16lx\n\r",
+ printk(" EI_STAT reg = %16lx\n",
frame->ei_stat);
- printk("\tLD_LOCK\t\t\t\t= %16lx\n\r",
+ printk(" LD_LOCK = %16lx\n",
frame->ld_lock);
}
@@ -547,7 +558,8 @@ mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
if (mcheck_expected(cpu)) {
mcpcia_pci_clr_err(mcheck_extra(cpu));
} else {
- /* FIXME: how do we figure out which hose the error was on? */
+ /* FIXME: how do we figure out which hose the
+ error was on? */
struct pci_controler *hose;
for (hose = hose_head; hose; hose = hose->next)
mcpcia_pci_clr_err(hose2mid(hose->index));
diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c
index a6b1a70c7..972e707cb 100644
--- a/arch/alpha/kernel/core_polaris.c
+++ b/arch/alpha/kernel/core_polaris.c
@@ -146,7 +146,7 @@ polaris_write_config_word(struct pci_dev *dev, int where, u16 value)
__kernel_stw(value, *(vusp)pci_addr);
mb();
- __kernel_ldbu(*(vusp)pci_addr);
+ __kernel_ldwu(*(vusp)pci_addr);
return PCIBIOS_SUCCESSFUL;
}
@@ -176,7 +176,7 @@ struct pci_ops polaris_pci_ops =
};
void __init
-polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+polaris_init_arch(void)
{
struct pci_controler *hose;
@@ -192,7 +192,7 @@ polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
+ hose = alloc_pci_controler();
hose->io_space = &ioport_resource;
hose->mem_space = &iomem_resource;
hose->config_space = POLARIS_DENSE_CONFIG_BASE;
diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c
index 4f9dd9a81..ee18e1472 100644
--- a/arch/alpha/kernel/core_pyxis.c
+++ b/arch/alpha/kernel/core_pyxis.c
@@ -285,7 +285,7 @@ struct pci_ops pyxis_pci_ops =
};
void __init
-pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+pyxis_init_arch(void)
{
struct pci_controler *hose;
unsigned int temp;
@@ -379,7 +379,7 @@ pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
+ hose = alloc_pci_controler();
hose->io_space = &ioport_resource;
hose->mem_space = &iomem_resource;
hose->config_space = PYXIS_CONF;
@@ -389,8 +389,10 @@ pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
static inline void
pyxis_pci_clr_err(void)
{
- *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = 0x0180;
+ unsigned int tmp;
+
+ tmp = *(vuip)PYXIS_ERR;
+ *(vuip)PYXIS_ERR = tmp;
mb();
*(vuip)PYXIS_ERR; /* re-read to force write */
}
diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
index 6028e4e58..079ad445c 100644
--- a/arch/alpha/kernel/core_t2.c
+++ b/arch/alpha/kernel/core_t2.c
@@ -322,7 +322,7 @@ struct pci_ops t2_pci_ops =
};
void __init
-t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+t2_init_arch(void)
{
struct pci_controler *hose;
unsigned int i;
@@ -384,7 +384,7 @@ t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
+ hose = alloc_pci_controler();
hose->io_space = &ioport_resource;
hose->mem_space = &iomem_resource;
hose->config_space = T2_CONF;
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index b27298bd5..dab4e1733 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -26,6 +26,13 @@
int TSUNAMI_bootcpu;
+static struct
+{
+ unsigned long wsba[4];
+ unsigned long wsm[4];
+ unsigned long tba[4];
+} saved_pchip[2];
+
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
* One plausible explanation is that the I/O controller does not properly
@@ -84,7 +91,7 @@ static int
mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
- struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ struct pci_controler *hose = dev->sysdata;
unsigned long addr;
u8 bus = dev->bus->number;
u8 device_fn = dev->devfn;
@@ -154,6 +161,8 @@ tsunami_write_config_byte(struct pci_dev *dev, int where, u8 value)
return PCIBIOS_DEVICE_NOT_FOUND;
__kernel_stb(value, *(vucp)addr);
+ mb();
+ __kernel_ldbu(*(vucp)addr);
return PCIBIOS_SUCCESSFUL;
}
@@ -167,6 +176,8 @@ tsunami_write_config_word(struct pci_dev *dev, int where, u16 value)
return PCIBIOS_DEVICE_NOT_FOUND;
__kernel_stw(value, *(vusp)addr);
+ mb();
+ __kernel_ldwu(*(vusp)addr);
return PCIBIOS_SUCCESSFUL;
}
@@ -180,6 +191,8 @@ tsunami_write_config_dword(struct pci_dev *dev, int where, u32 value)
return PCIBIOS_DEVICE_NOT_FOUND;
*(vuip)addr = value;
+ mb();
+ *(vuip)addr;
return PCIBIOS_SUCCESSFUL;
}
@@ -243,31 +256,55 @@ tsunami_probe_write(volatile unsigned long *vaddr)
#define FN __FUNCTION__
static void __init
-tsunami_init_one_pchip(tsunami_pchip *pchip, int index,
- unsigned long *mem_start)
+tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
{
struct pci_controler *hose;
if (tsunami_probe_read(&pchip->pctl.csr) == 0)
return;
- hose = alloc_pci_controler(mem_start);
- hose->io_space = alloc_resource(mem_start);
- hose->mem_space = alloc_resource(mem_start);
+ hose = alloc_pci_controler();
+ hose->io_space = alloc_resource();
+ hose->mem_space = alloc_resource();
hose->config_space = TSUNAMI_CONF(index);
hose->index = index;
hose->io_space->start = TSUNAMI_IO(index) - TSUNAMI_IO_BIAS;
- hose->io_space->end = hose->io_space->start + 0xffff;
+ hose->io_space->end = hose->io_space->start + TSUNAMI_IO_SPACE - 1;
hose->io_space->name = pci_io_names[index];
+ hose->io_space->flags = IORESOURCE_IO;
hose->mem_space->start = TSUNAMI_MEM(index) - TSUNAMI_MEM_BIAS;
hose->mem_space->end = hose->mem_space->start + 0xffffffff;
hose->mem_space->name = pci_mem_names[index];
+ hose->mem_space->flags = IORESOURCE_MEM;
+
+ if (request_resource(&ioport_resource, hose->io_space) < 0)
+ printk(KERN_ERR "Failed to request IO on hose %d\n", index);
+ if (request_resource(&iomem_resource, hose->mem_space) < 0)
+ printk(KERN_ERR "Failed to request MEM on hose %d\n", index);
+
+ /*
+ * Save the existing PCI window translations. SRM will
+ * need them when we go to reboot.
+ */
+
+ saved_pchip[index].wsba[0] = pchip->wsba[0].csr;
+ saved_pchip[index].wsm[0] = pchip->wsm[0].csr;
+ saved_pchip[index].tba[0] = pchip->tba[0].csr;
+
+ saved_pchip[index].wsba[1] = pchip->wsba[1].csr;
+ saved_pchip[index].wsm[1] = pchip->wsm[1].csr;
+ saved_pchip[index].tba[1] = pchip->tba[1].csr;
+
+ saved_pchip[index].wsba[2] = pchip->wsba[2].csr;
+ saved_pchip[index].wsm[2] = pchip->wsm[2].csr;
+ saved_pchip[index].tba[2] = pchip->tba[2].csr;
- request_resource(&ioport_resource, hose->io_space);
- request_resource(&iomem_resource, hose->mem_space);
+ saved_pchip[index].wsba[3] = pchip->wsba[3].csr;
+ saved_pchip[index].wsm[3] = pchip->wsm[3].csr;
+ saved_pchip[index].tba[3] = pchip->tba[3].csr;
/*
* Set up the PCI->physical memory translation windows.
@@ -294,7 +331,7 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index,
}
void __init
-tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+tsunami_init_arch(void)
{
#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
extern asmlinkage void entInt(void);
@@ -338,9 +375,37 @@ tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end)
/* Find how many hoses we have, and initialize them. TSUNAMI
and TYPHOON can have 2, but might only have 1 (DS10). */
- tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start);
+ tsunami_init_one_pchip(TSUNAMI_pchip0, 0);
+ if (TSUNAMI_cchip->csc.csr & 1L<<14)
+ tsunami_init_one_pchip(TSUNAMI_pchip1, 1);
+}
+
+static void
+tsunami_kill_one_pchip(tsunami_pchip *pchip, int index)
+{
+ pchip->wsba[0].csr = saved_pchip[index].wsba[0];
+ pchip->wsm[0].csr = saved_pchip[index].wsm[0];
+ pchip->tba[0].csr = saved_pchip[index].tba[0];
+
+ pchip->wsba[1].csr = saved_pchip[index].wsba[1];
+ pchip->wsm[1].csr = saved_pchip[index].wsm[1];
+ pchip->tba[1].csr = saved_pchip[index].tba[1];
+
+ pchip->wsba[2].csr = saved_pchip[index].wsba[2];
+ pchip->wsm[2].csr = saved_pchip[index].wsm[2];
+ pchip->tba[2].csr = saved_pchip[index].tba[2];
+
+ pchip->wsba[3].csr = saved_pchip[index].wsba[3];
+ pchip->wsm[3].csr = saved_pchip[index].wsm[3];
+ pchip->tba[3].csr = saved_pchip[index].tba[3];
+}
+
+void
+tsunami_kill_arch(int mode)
+{
+ tsunami_kill_one_pchip(TSUNAMI_pchip0, 0);
if (TSUNAMI_cchip->csc.csr & 1L<<14)
- tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
+ tsunami_kill_one_pchip(TSUNAMI_pchip1, 1);
}
static inline void
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index 43da6affd..d6d6e0611 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -22,15 +22,14 @@
#include <linux/random.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/irq.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/machvec.h>
#include "proto.h"
-#include "irq_impl.h"
#define vulp volatile unsigned long *
#define vuip volatile unsigned int *
@@ -42,8 +41,8 @@ int __local_irq_count;
int __local_bh_count;
#endif
-#if NR_IRQS > 64
-# error Unable to handle more than 64 irq levels.
+#if NR_IRQS > 128
+# error Unable to handle more than 128 irq levels.
#endif
#ifdef CONFIG_ALPHA_GENERIC
@@ -60,7 +59,8 @@ int __local_bh_count;
/*
* Shadow-copy of masked interrupts.
*/
-unsigned long alpha_irq_mask = ~0UL;
+
+unsigned long _alpha_irq_masks[2] = { ~0UL, ~0UL };
/*
* The ack_irq routine used by 80% of the systems.
@@ -110,6 +110,8 @@ void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
# define IACK_SC TSUNAMI_IACK_SC
#elif defined(CONFIG_ALPHA_POLARIS)
# define IACK_SC POLARIS_IACK_SC
+#elif defined(CONFIG_ALPHA_IRONGATE)
+# define IACK_SC IRONGATE_IACK_SC
#else
/* This is bogus but necessary to get it to compile on all platforms. */
# define IACK_SC 1L
@@ -179,19 +181,22 @@ srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
*/
static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction *irq_action[NR_IRQS];
+spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = {0,} };
static inline void
mask_irq(unsigned long irq)
{
- alpha_mv.update_irq_hw(irq, alpha_irq_mask |= 1UL << irq, 0);
+ set_bit(irq, _alpha_irq_masks);
+ alpha_mv.update_irq_hw(irq, alpha_irq_mask, 0);
}
static inline void
unmask_irq(unsigned long irq)
{
- alpha_mv.update_irq_hw(irq, alpha_irq_mask &= ~(1UL << irq), 1);
+ clear_bit(irq, _alpha_irq_masks);
+ alpha_mv.update_irq_hw(irq, alpha_irq_mask, 1);
}
void
@@ -225,12 +230,7 @@ enable_irq(unsigned int irq_nr)
int
check_irq(unsigned int irq)
{
- struct irqaction **p;
-
- p = irq_action + irq;
- if (*p == NULL)
- return 0;
- return -EBUSY;
+ return irq_desc[irq].action ? -EBUSY : 0;
}
int
@@ -248,7 +248,7 @@ request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
if (!handler)
return -EINVAL;
- p = irq_action + irq;
+ p = &irq_desc[irq].action;
action = *p;
if (action) {
/* Can't share interrupts unless both agree to */
@@ -309,14 +309,14 @@ free_irq(unsigned int irq, void *dev_id)
printk("Trying to free reserved IRQ %d\n", irq);
return;
}
- for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+ for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
if (action->dev_id != dev_id)
continue;
/* Found it - now free it */
save_and_cli(flags);
*p = action->next;
- if (!irq[irq_action])
+ if (!irq_desc[irq].action)
mask_irq(irq);
restore_flags(flags);
kfree(action);
@@ -339,7 +339,7 @@ int get_irq_list(char *buf)
#endif
for (i = 0; i < NR_IRQS; i++) {
- action = irq_action[i];
+ action = irq_desc[i].action;
if (!action)
continue;
p += sprintf(p, "%3d: ",i);
@@ -387,8 +387,6 @@ static void *previous_irqholder = NULL;
static void show(char * str, void *where);
-#define SYNC_OTHER_CPUS(x) udelay((x)+1);
-
static inline void
wait_on_irq(int cpu, void *where)
{
@@ -409,7 +407,6 @@ wait_on_irq(int cpu, void *where)
/* Duh, we have to loop. Release the lock to avoid deadlocks */
spin_unlock(&global_irq_lock);
- mb();
for (;;) {
if (!--count) {
@@ -417,7 +414,7 @@ wait_on_irq(int cpu, void *where)
count = MAXCOUNT;
}
__sti();
- SYNC_OTHER_CPUS(cpu);
+ udelay(1); /* make sure to run pending irqs */
__cli();
if (atomic_read(&global_irq_count))
@@ -437,17 +434,13 @@ static inline void
get_irqlock(int cpu, void* where)
{
if (!spin_trylock(&global_irq_lock)) {
- /* do we already hold the lock? */
- if (cpu == global_irq_holder) {
-#if 0
- printk("get_irqlock: already held at %08lx\n",
- previous_irqholder);
-#endif
+ /* Do we already hold the lock? */
+ if (cpu == global_irq_holder)
return;
- }
- /* Uhhuh.. Somebody else got it. Wait.. */
+ /* Uhhuh.. Somebody else got it. Wait. */
spin_lock(&global_irq_lock);
}
+
/*
* Ok, we got the lock bit.
* But that's actually just the easy part.. Now
@@ -543,63 +536,6 @@ __global_restore_flags(unsigned long flags)
}
}
-#undef INIT_STUCK
-#define INIT_STUCK (1<<26)
-
-#undef STUCK
-#define STUCK \
- if (!--stuck) { \
- printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \
- irq, cpu, global_irq_holder); \
- stuck = INIT_STUCK; \
- }
-
-#undef VERBOSE_IRQLOCK_DEBUGGING
-
-void
-irq_enter(int cpu, int irq)
-{
-#ifdef VERBOSE_IRQLOCK_DEBUGGING
- extern void smp_show_backtrace_all_cpus(void);
-#endif
- int stuck = INIT_STUCK;
-
- hardirq_enter(cpu, irq);
- barrier();
- while (spin_is_locked(&global_irq_lock)) {
- if (cpu == global_irq_holder) {
- int globl_locked = spin_is_locked(&global_irq_lock);
- int globl_icount = atomic_read(&global_irq_count);
- int local_count = local_irq_count(cpu);
-
- /* It is very important that we load the state
- variables before we do the first call to
- printk() as printk() could end up changing
- them... */
-
- printk("CPU[%d]: where [%p] glocked[%d] gicnt[%d]"
- " licnt[%d]\n",
- cpu, previous_irqholder, globl_locked,
- globl_icount, local_count);
-#ifdef VERBOSE_IRQLOCK_DEBUGGING
- printk("Performing backtrace on all CPUs,"
- " write this down!\n");
- smp_show_backtrace_all_cpus();
-#endif
- break;
- }
- STUCK;
- barrier();
- }
-}
-
-void
-irq_exit(int cpu, int irq)
-{
- hardirq_exit(cpu, irq);
- release_irqlock(cpu);
-}
-
static void
show(char * str, void *where)
{
@@ -700,12 +636,6 @@ synchronize_irq(void)
}
#endif
}
-
-#else /* !__SMP__ */
-
-#define irq_enter(cpu, irq) (++local_irq_count(cpu))
-#define irq_exit(cpu, irq) (--local_irq_count(cpu))
-
#endif /* __SMP__ */
static void
@@ -722,7 +652,7 @@ unexpected_irq(int irq, struct pt_regs * regs)
printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
printk("Expecting: ");
for (i = 0; i < ACTUAL_NR_IRQS; i++)
- if ((action = irq_action[i]))
+ if ((action = irq_desc[i].action))
while (action->handler) {
printk("[%s:%d] ", action->name, i);
action = action->next;
@@ -776,7 +706,7 @@ handle_irq(int irq, int ack, struct pt_regs * regs)
irq_enter(cpu, irq);
kstat.irqs[cpu][irq] += 1;
- action = irq_action[irq];
+ action = irq_desc[irq].action;
/*
* For normal interrupts, we mask it out, and then ACK it.
@@ -819,11 +749,13 @@ probe_irq_on(void)
unsigned long delay;
unsigned int i;
- for (i = ACTUAL_NR_IRQS - 1; i > 0; i--) {
+ /* Handle only the first 64 IRQs here. This is enough for
+ [E]ISA, which is the only thing that needs probing anyway. */
+ for (i = (ACTUAL_NR_IRQS - 1) & 63; i > 0; i--) {
if (!(PROBE_MASK & (1UL << i))) {
continue;
}
- action = irq_action[i];
+ action = irq_desc[i].action;
if (!action) {
enable_irq(i);
irqs |= (1UL << i);
@@ -852,6 +784,8 @@ probe_irq_off(unsigned long irqs)
{
int i;
+ /* Handle only the first 64 IRQs here. This is enough for
+ [E]ISA, which is the only thing that needs probing anyway. */
irqs &= alpha_irq_mask;
if (!irqs)
return 0;
diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
deleted file mode 100644
index bc8854212..000000000
--- a/arch/alpha/kernel/irq_impl.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * linux/arch/alpha/kernel/irq.h
- *
- * Copyright (C) 1995 Linus Torvalds
- * Copyright (C) 1998 Richard Henderson
- *
- * This file contains declarations and inline functions for interfacing
- * with the IRQ handling routines in irq.c.
- */
-
-#include <linux/config.h>
-
-#define STANDARD_INIT_IRQ_PROLOG \
- outb(0, DMA1_RESET_REG); \
- outb(0, DMA2_RESET_REG); \
- outb(0, DMA1_CLR_MASK_REG); \
- outb(0, DMA2_CLR_MASK_REG)
-
-extern unsigned long alpha_irq_mask;
-
-extern void common_ack_irq(unsigned long irq);
-extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs);
-extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs);
-
-extern void handle_irq(int irq, int ack, struct pt_regs * regs);
-
-#define RTC_IRQ 8
-#ifdef CONFIG_RTC
-#define TIMER_IRQ 0 /* timer is the pit */
-#else
-#define TIMER_IRQ RTC_IRQ /* timer is the rtc */
-#endif
-
-extern char _stext;
-static inline void alpha_do_profile (unsigned long pc)
-{
- if (prof_buffer && current->pid) {
- pc -= (unsigned long) &_stext;
- pc >>= prof_shift;
- /*
- * Don't ignore out-of-bounds PC values silently,
- * put them into the last histogram slot, so if
- * present, they will show up as a sharp peak.
- */
- if (pc > prof_len - 1)
- pc = prof_len - 1;
- atomic_inc((atomic_t *)&prof_buffer[pc]);
- }
-}
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index a0ff70dcc..fc0d0cc0c 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -7,12 +7,14 @@
*/
#include <linux/config.h>
+#include <asm/pgalloc.h>
-/* Whee. Both TSUNAMI and POLARIS don't have an HAE. Fix things up for
+/* Whee. IRONGATE, POLARIS and TSUNAMI don't have an HAE. Fix things up for
the GENERIC kernel by defining the HAE address to be that of the cache.
Now we can read and write it as we like. ;-) */
-#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
+#define IRONGATE_HAE_ADDRESS (&alpha_mv.hae_cache)
#define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache)
+#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
#if CIA_ONE_HAE_WINDOW
#define CIA_HAE_ADDRESS (&alpha_mv.hae_cache)
@@ -90,10 +92,11 @@
#define DO_APECS_IO IO(APECS,apecs)
#define DO_CIA_IO IO(CIA,cia)
+#define DO_IRONGATE_IO IO(IRONGATE,irongate)
#define DO_LCA_IO IO(LCA,lca)
#define DO_MCPCIA_IO IO(MCPCIA,mcpcia)
-#define DO_PYXIS_IO IO(PYXIS,pyxis)
#define DO_POLARIS_IO IO(POLARIS,polaris)
+#define DO_PYXIS_IO IO(PYXIS,pyxis)
#define DO_T2_IO IO(T2,t2)
#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami)
@@ -103,6 +106,7 @@
#define DO_APECS_BUS BUS(apecs)
#define DO_CIA_BUS BUS(cia)
+#define DO_IRONGATE_BUS BUS(irongate)
#define DO_LCA_BUS BUS(lca)
#define DO_MCPCIA_BUS BUS(mcpcia)
#define DO_PYXIS_BUS BUS(pyxis)
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 39d6b759f..9a61a4e99 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -6,10 +6,14 @@
* David Mosberger (davidm@cs.arizona.edu)
*/
+/* 2.3.x PCI/resources, 1999 Andrea Arcangeli <andrea@suse.de> */
+
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/bootmem.h>
#include <asm/machvec.h>
#include "proto.h"
@@ -36,7 +40,6 @@ const char pci_hae0_name[] = "HAE0";
*/
struct pci_controler *hose_head, **hose_tail = &hose_head;
-struct pci_controler *probing_hose;
/*
* Quirks.
@@ -54,32 +57,122 @@ quirk_isa_bridge(struct pci_dev *dev)
dev->class = PCI_CLASS_BRIDGE_ISA;
}
+static void __init
+quirk_vga_enable_rom(struct pci_dev *dev)
+{
+ /* If it's a VGA, enable its BIOS ROM at C0000.
+ But if its a Cirrus 543x/544x DISABLE it, since
+ enabling ROM disables the memory... */
+ if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA &&
+ /* But if its a Cirrus 543x/544x DISABLE it */
+ (dev->vendor != PCI_VENDOR_ID_CIRRUS ||
+ (dev->device < 0x00a0) || (dev->device > 0x00ac)))
+ {
+ u32 reg;
+
+ pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+ reg |= PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(dev, dev->rom_base_reg, reg);
+ dev->resource[PCI_ROM_RESOURCE].flags |= PCI_ROM_ADDRESS_ENABLE;
+ }
+}
+
struct pci_fixup pcibios_fixups[] __initdata = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
quirk_eisa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
quirk_isa_bridge },
+ { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom },
{ 0 }
};
+#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
+#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+#define KB 1024
+#define MB (1024*KB)
+#define GB (1024*MB)
+
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+ struct pci_dev * dev = data;
+ unsigned long alignto;
+ unsigned long start = res->start;
+
+ if (res->flags & IORESOURCE_IO) {
+ /*
+ * Aligning to 0x800 rather than the minimum base of
+ * 0x400 is an attempt to avoid having devices in
+ * any 0x?C?? range, which is where the de4x5 driver
+ * probes for EISA cards.
+ *
+ * Adaptecs, especially, resent such intrusions.
+ */
+ alignto = MAX(0x800, size);
+ start = ALIGN(start, alignto);
+ }
+ else if (res->flags & IORESOURCE_MEM) {
+ /*
+ * The following holds at least for the Low Cost
+ * Alpha implementation of the PCI interface:
+ *
+ * In sparse memory address space, the first
+ * octant (16MB) of every 128MB segment is
+ * aliased to the very first 16 MB of the
+ * address space (i.e., it aliases the ISA
+ * memory address space). Thus, we try to
+ * avoid allocating PCI devices in that range.
+ * Can be allocated in 2nd-7th octant only.
+ * Devices that need more than 112MB of
+ * address space must be accessed through
+ * dense memory space only!
+ */
+
+ /* Align to multiple of size of minimum base. */
+ alignto = MAX(0x1000, size);
+ start = ALIGN(start, alignto);
+ if (size > 7 * 16*MB) {
+ printk(KERN_WARNING "PCI: dev %s "
+ "requests %ld bytes of contiguous "
+ "address space---don't use sparse "
+ "memory accesses on this device!\n",
+ dev->name, size);
+ } else {
+ if (((start / (16*MB)) & 0x7) == 0) {
+ start &= ~(128*MB - 1);
+ start += 16*MB;
+ start = ALIGN(start, alignto);
+ }
+ if (start/(128*MB) != (start + size)/(128*MB)) {
+ start &= ~(128*MB - 1);
+ start += (128 + 16)*MB;
+ start = ALIGN(start, alignto);
+ }
+ }
+ }
+
+ res->start = start;
+}
+#undef MAX
+#undef ALIGN
+#undef KB
+#undef MB
+#undef GB
/*
* Pre-layout host-independant device initialization.
*/
static void __init
-pcibios_assign_special(void)
+pcibios_assign_special(struct pci_dev * dev)
{
- struct pci_dev *dev;
int i;
/* The first three resources of an IDE controler are often magic,
so leave them unchanged. This is true, for instance, of the
Contaq 82C693 as seen on SX164 and DP264. */
- for (dev = pci_devices; dev; dev = dev->next) {
- if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE)
- continue;
+ if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
/* Resource 1 of IDE controller is the address of HD_CMD
register which actually occupies a single byte (0x3f6
for ide0) in reported 0x3f4-3f7 range. We have to fix
@@ -87,11 +180,20 @@ pcibios_assign_special(void)
controller. */
dev->resource[1].start += 2;
dev->resource[1].end = dev->resource[1].start;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- if (dev->resource[i].flags)
+ for (i = 0; i < PCI_NUM_RESOURCES; i++)
+ if (dev->resource[i].flags && dev->resource[i].start)
pci_claim_resource(dev, i);
- }
}
+ /*
+ * We don't have code that will init the CYPRESS bridge correctly
+ * so we do the next best thing, and depend on the previous
+ * console code to do the right thing, and ignore it here... :-\
+ */
+ else if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
+ dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
+ for (i = 0; i < PCI_NUM_RESOURCES; i++)
+ if (dev->resource[i].flags && dev->resource[i].start)
+ pci_claim_resource(dev, i);
}
@@ -110,31 +212,65 @@ pcibios_setup(char *str)
}
void __init
+pcibios_fixup_resource(struct resource *res, struct resource *root)
+{
+ res->start += root->start;
+ res->end += root->start;
+}
+
+void __init
+pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
+{
+ /* Update device resources. */
+
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ pcibios_fixup_resource(&dev->resource[i],
+ bus->resource[0]);
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ pcibios_fixup_resource(&dev->resource[i],
+ bus->resource[1]);
+ }
+ pcibios_assign_special(dev);
+}
+
+void __init
pcibios_fixup_bus(struct pci_bus *bus)
{
/* Propogate hose info into the subordinate devices. */
- struct pci_controler *hose = probing_hose;
+ struct pci_controler *hose = (struct pci_controler *) bus->sysdata;
struct pci_dev *dev;
bus->resource[0] = hose->io_space;
bus->resource[1] = hose->mem_space;
- for (dev = bus->devices; dev; dev = dev->sibling)
- dev->sysdata = hose;
+ for (dev = bus->devices; dev; dev = dev->sibling) {
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
+ }
}
void __init
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, &reg);
- reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
+ int where;
+ u32 reg;
+
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ reg = (res->start - root->start) | (res->flags & 0xf);
+ pci_write_config_dword(dev, where, reg);
+ if ((res->flags & (PCI_BASE_ADDRESS_SPACE
+ | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
+ == (PCI_BASE_ADDRESS_SPACE_MEMORY
+ | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+ pci_write_config_dword(dev, where+4, 0);
+ printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name);
+ }
/* ??? FIXME -- record old value for shutdown. */
}
@@ -170,6 +306,16 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
}
void __init
+pcibios_fixup_pbus_ranges(struct pci_bus * bus,
+ struct pbus_set_ranges_data * ranges)
+{
+ ranges->io_start -= bus->resource[0]->start;
+ ranges->io_end -= bus->resource[0]->start;
+ ranges->mem_start -= bus->resource[1]->start;
+ ranges->mem_end -= bus->resource[1]->start;
+}
+
+void __init
common_init_pci(void)
{
struct pci_controler *hose;
@@ -180,15 +326,12 @@ common_init_pci(void)
for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
hose->first_busno = next_busno;
hose->last_busno = 0xff;
- probing_hose = hose;
bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose);
hose->bus = bus;
next_busno = hose->last_busno = bus->subordinate;
next_busno += 1;
}
- probing_hose = NULL;
- pcibios_assign_special();
pci_assign_unassigned_resources(alpha_mv.min_io_address,
alpha_mv.min_mem_address);
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
@@ -197,17 +340,11 @@ common_init_pci(void)
struct pci_controler * __init
-alloc_pci_controler(unsigned long *mem_start)
+alloc_pci_controler(void)
{
- unsigned long start = *mem_start;
struct pci_controler *hose;
- if (start & 31)
- start = (start | 31) + 1;
- hose = (void *) start;
- start = (unsigned long) (hose + 1);
- *mem_start = start;
- memset(hose, 0, sizeof(*hose));
+ hose = alloc_bootmem(sizeof(*hose));
*hose_tail = hose;
hose_tail = &hose->next;
@@ -216,17 +353,11 @@ alloc_pci_controler(unsigned long *mem_start)
}
struct resource * __init
-alloc_resource(unsigned long *mem_start)
+alloc_resource(void)
{
- unsigned long start = *mem_start;
struct resource *res;
- if (start & 31)
- start = (start | 31) + 1;
- res = (void *) start;
- start = (unsigned long) (res + 1);
- *mem_start = start;
- memset(res, 0, sizeof(*res));
+ res = alloc_bootmem(sizeof(*res));
return res;
}
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
index c7c97f096..b46fb9980 100644
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -125,12 +125,11 @@ static inline u8 bridge_swizzle(u8 pin, u8 slot)
/* The hose list. */
extern struct pci_controler *hose_head, **hose_tail;
-extern struct pci_controler *probing_hose;
extern void common_init_pci(void);
extern u8 common_swizzle(struct pci_dev *, u8 *);
-extern struct pci_controler *alloc_pci_controler(unsigned long *);
-extern struct resource *alloc_resource(unsigned long *);
+extern struct pci_controler *alloc_pci_controler(void);
+extern struct resource *alloc_resource(void);
extern const char *const pci_io_names[];
extern const char *const pci_mem_names[];
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 0390e3138..e80282155 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -94,8 +94,8 @@ cpu_idle(void)
}
}
-void
-common_kill_arch (int mode, char *restart_cmd)
+static void
+common_shutdown(int mode, char *restart_cmd)
{
/* The following currently only has any effect on SRM. We should
fix MILO to understand it. Should be pretty easy. Also we can
@@ -141,24 +141,12 @@ common_kill_arch (int mode, char *restart_cmd)
#ifdef CONFIG_RTC
/* Reset rtc to defaults. */
- {
- unsigned char control;
-
- cli();
-
- /* Reset periodic interrupt frequency. */
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
-
- /* Turn on periodic interrupts. */
- control = CMOS_READ(RTC_CONTROL);
- control |= RTC_PIE;
- CMOS_WRITE(control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
-
- sti();
- }
+ rtc_kill_pit();
#endif
+ if (alpha_mv.kill_arch)
+ alpha_mv.kill_arch(mode);
+
if (!alpha_using_srm && mode != LINUX_REBOOT_CMD_RESTART) {
/* Unfortunately, since MILO doesn't currently understand
the hwrpb bits above, we can't reliably halt the
@@ -175,21 +163,23 @@ common_kill_arch (int mode, char *restart_cmd)
void
machine_restart(char *restart_cmd)
{
- alpha_mv.kill_arch(LINUX_REBOOT_CMD_RESTART, restart_cmd);
+ common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
}
void
machine_halt(void)
{
- alpha_mv.kill_arch(LINUX_REBOOT_CMD_HALT, NULL);
+ common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
}
-void machine_power_off(void)
+void
+machine_power_off(void)
{
- alpha_mv.kill_arch(LINUX_REBOOT_CMD_POWER_OFF, NULL);
+ common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
}
-void show_regs(struct pt_regs * regs)
+void
+show_regs(struct pt_regs * regs)
{
printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc);
printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
@@ -210,7 +200,8 @@ void show_regs(struct pt_regs * regs)
/*
* Re-start a thread when doing execve()
*/
-void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
+void
+start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
set_fs(USER_DS);
regs->pc = pc;
@@ -221,11 +212,13 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
/*
* Free current thread data structures etc..
*/
-void exit_thread(void)
+void
+exit_thread(void)
{
}
-void flush_thread(void)
+void
+flush_thread(void)
{
/* Arrange for each exec'ed process to start off with a clean slate
with respect to the FPU. This is all exceptions disabled. Note
@@ -236,7 +229,8 @@ void flush_thread(void)
wrfpcr(FPCR_DYN_NORMAL | FPCR_INVD | FPCR_DZED | FPCR_OVFD | FPCR_INED);
}
-void release_thread(struct task_struct *dead_task)
+void
+release_thread(struct task_struct *dead_task)
{
}
@@ -249,15 +243,17 @@ void release_thread(struct task_struct *dead_task)
* Notice that "fork()" is implemented in terms of clone,
* with parameters (SIGCHLD, 0).
*/
-int alpha_clone(unsigned long clone_flags, unsigned long usp,
- struct switch_stack * swstack)
+int
+alpha_clone(unsigned long clone_flags, unsigned long usp,
+ struct switch_stack * swstack)
{
if (!usp)
usp = rdusp();
return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1));
}
-int alpha_vfork(struct switch_stack * swstack)
+int
+alpha_vfork(struct switch_stack * swstack)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
(struct pt_regs *) (swstack+1));
@@ -274,8 +270,9 @@ int alpha_vfork(struct switch_stack * swstack)
* for a kernel fork().
*/
-int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
- struct task_struct * p, struct pt_regs * regs)
+int
+copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ struct task_struct * p, struct pt_regs * regs)
{
extern void ret_from_sys_call(void);
extern void ret_from_smp_fork(void);
@@ -313,7 +310,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
/*
* fill in the user structure for a core dump..
*/
-void dump_thread(struct pt_regs * pt, struct user * dump)
+void
+dump_thread(struct pt_regs * pt, struct user * dump)
{
/* switch stack follows right below pt_regs: */
struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
@@ -370,7 +368,8 @@ void dump_thread(struct pt_regs * pt, struct user * dump)
memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
}
-int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
+int
+dump_fpu(struct pt_regs * regs, elf_fpregset_t *r)
{
/* switch stack follows right below pt_regs: */
struct switch_stack * sw = ((struct switch_stack *) regs) - 1;
@@ -388,7 +387,8 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
*
* Don't do this at home.
*/
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+asmlinkage int
+sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs regs)
{
@@ -415,7 +415,8 @@ extern void scheduling_functions_end_here(void);
#define first_sched ((unsigned long) scheduling_functions_start_here)
#define last_sched ((unsigned long) scheduling_functions_end_here)
-unsigned long get_wchan(struct task_struct *p)
+unsigned long
+get_wchan(struct task_struct *p)
{
unsigned long schedule_frame;
unsigned long pc;
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 2a196efa1..3efbdda08 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -12,43 +12,51 @@ struct pci_dev;
/* core_apecs.c */
extern struct pci_ops apecs_pci_ops;
-extern void apecs_init_arch(unsigned long *, unsigned long *);
+extern void apecs_init_arch(void);
extern void apecs_pci_clr_err(void);
extern void apecs_machine_check(u64, u64, struct pt_regs *);
/* core_cia.c */
extern struct pci_ops cia_pci_ops;
-extern void cia_init_arch(unsigned long *, unsigned long *);
+extern void cia_init_arch(void);
extern void cia_machine_check(u64, u64, struct pt_regs *);
+/* core_irongate.c */
+extern struct pci_ops irongate_pci_ops;
+extern int irongate_pci_clr_err(void);
+extern void irongate_init_arch(void);
+extern void irongate_machine_check(u64, u64, struct pt_regs *);
+
/* core_lca.c */
extern struct pci_ops lca_pci_ops;
-extern void lca_init_arch(unsigned long *, unsigned long *);
+extern void lca_init_arch(void);
extern void lca_machine_check(u64, u64, struct pt_regs *);
/* core_mcpcia.c */
extern struct pci_ops mcpcia_pci_ops;
-extern void mcpcia_init_arch(unsigned long *, unsigned long *);
+extern void mcpcia_init_arch(void);
+extern void mcpcia_init_hoses(void);
extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
/* core_polaris.c */
extern struct pci_ops polaris_pci_ops;
-extern void polaris_init_arch(unsigned long *, unsigned long *);
+extern void polaris_init_arch(void);
extern void polaris_machine_check(u64, u64, struct pt_regs *);
/* core_pyxis.c */
extern struct pci_ops pyxis_pci_ops;
-extern void pyxis_init_arch(unsigned long *, unsigned long *);
+extern void pyxis_init_arch(void);
extern void pyxis_machine_check(u64, u64, struct pt_regs *);
/* core_t2.c */
extern struct pci_ops t2_pci_ops;
-extern void t2_init_arch(unsigned long *, unsigned long *);
+extern void t2_init_arch(void);
extern void t2_machine_check(u64, u64, struct pt_regs *);
/* core_tsunami.c */
extern struct pci_ops tsunami_pci_ops;
-extern void tsunami_init_arch(unsigned long *, unsigned long *);
+extern void tsunami_init_arch(void);
+extern void tsunami_kill_arch(int);
extern void tsunami_machine_check(u64, u64, struct pt_regs *);
/* setup.c */
@@ -67,6 +75,7 @@ extern int smp_boot_cpuid;
/* time.c */
extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
extern void rtc_init_pit(void);
+extern void rtc_kill_pit(void);
extern void common_init_pit(void);
extern unsigned long est_cycle_freq;
@@ -102,7 +111,6 @@ extern void entUna(void);
extern void entDbg(void);
/* process.c */
-extern void common_kill_arch (int mode, char *reboot_cmd);
extern void cpu_idle(void) __attribute__((noreturn));
/* ptrace.c */
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 333bb63ec..b650de6b1 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -57,12 +57,6 @@ enum {
* | | v
* +================================+
*/
-#define PT_REG(reg) (PAGE_SIZE*2 - sizeof(struct pt_regs) \
- + (long)&((struct pt_regs *)0)->reg)
-
-#define SW_REG(reg) (PAGE_SIZE*2 - sizeof(struct pt_regs) \
- - sizeof(struct switch_stack) \
- + (long)&((struct switch_stack *)0)->reg)
/*
* The following table maps a register index into the stack offset at
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 9bb21671c..3a1fb94a3 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -4,6 +4,8 @@
* Copyright (C) 1995 Linus Torvalds
*/
+/* 2.3.x bootmem, 1999 Andrea Arcangeli <andrea@suse.de> */
+
/*
* Bootup setup stuff.
*/
@@ -26,6 +28,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/ioport.h>
+#include <linux/bootmem.h>
#ifdef CONFIG_RTC
#include <linux/timex.h>
@@ -40,6 +43,8 @@
#include <asm/hwrpb.h>
#include <asm/dma.h>
#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/mmu_context.h>
#include "proto.h"
#include "pci_impl.h"
@@ -57,7 +62,6 @@ unsigned char aux_device_present = 0xaa;
#define N(a) (sizeof(a)/sizeof(a[0]))
-static unsigned long find_end_memory(void);
static struct alpha_machine_vector *get_sysvec(long, long, long);
static struct alpha_machine_vector *get_sysvec_byname(const char *);
static void get_sysnames(long, long, char **, char **);
@@ -68,7 +72,7 @@ static void get_sysnames(long, long, char **, char **);
* initialized, we need to copy things out into a more permanent
* place.
*/
-#define PARAM ZERO_PAGE(0)
+#define PARAM ZERO_PGE
#define COMMAND_LINE ((char*)(PARAM + 0x0000))
#define COMMAND_LINE_SIZE 256
#define INITRD_START (*(unsigned long *) (PARAM+0x100))
@@ -115,12 +119,14 @@ WEAK(eb164_mv);
WEAK(eb64p_mv);
WEAK(eb66_mv);
WEAK(eb66p_mv);
+WEAK(eiger_mv);
WEAK(jensen_mv);
WEAK(lx164_mv);
WEAK(miata_mv);
WEAK(mikasa_mv);
WEAK(mikasa_primo_mv);
WEAK(monet_mv);
+WEAK(nautilus_mv);
WEAK(noname_mv);
WEAK(noritake_mv);
WEAK(noritake_primo_mv);
@@ -181,17 +187,181 @@ reserve_std_resources(void)
request_resource(io, standard_io_resources+i);
}
-void __init
-setup_arch(char **cmdline_p, unsigned long * memory_start_p,
- unsigned long * memory_end_p)
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+#define PFN_MAX PFN_DOWN(0x80000000)
+#define for_each_mem_cluster(memdesc, cluster, i) \
+ for ((cluster) = (memdesc)->cluster, (i) = 0; \
+ (i) < (memdesc)->numclusters; (i)++, (cluster)++)
+
+static void __init
+setup_memory(void)
{
+ struct memclust_struct * cluster;
+ struct memdesc_struct * memdesc;
+ unsigned long start_pfn, bootmap_size, bootmap_pages, bootmap_start;
+ unsigned long start, end;
extern char _end[];
+ int i;
+
+ /* Find free clusters, and init and free the bootmem accordingly. */
+ memdesc = (struct memdesc_struct *)
+ (hwrpb->mddt_offset + (unsigned long) hwrpb);
+
+ for_each_mem_cluster(memdesc, cluster, i) {
+ printk("memcluster %d, usage %01lx, start %8lu, end %8lu\n",
+ i, cluster->usage, cluster->start_pfn,
+ cluster->start_pfn + cluster->numpages);
+
+ /* Bit 0 is console/PALcode reserved. Bit 1 is
+ non-volatile memory -- we might want to mark
+ this for later. */
+ if (cluster->usage & 3)
+ continue;
+
+ end = cluster->start_pfn + cluster->numpages;
+ if (end > max_low_pfn)
+ max_low_pfn = end;
+ }
+
+ /* Enforce maximum of 2GB even if there is more. Blah. */
+ if (max_low_pfn > PFN_MAX)
+ max_low_pfn = PFN_MAX;
+ printk("max_low_pfn %ld\n", max_low_pfn);
+
+ /* Find the end of the kernel memory. */
+ start_pfn = PFN_UP(virt_to_phys(_end));
+ printk("_end %p, start_pfn %ld\n", _end, start_pfn);
+
+ bootmap_start = -1;
+
+ try_again:
+ if (max_low_pfn <= start_pfn)
+ panic("not enough memory to boot");
+
+ /* We need to know how many physically contigous pages
+ we'll need for the bootmap. */
+ bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
+ printk("bootmap size: %ld pages\n", bootmap_pages);
+
+ /* Now find a good region where to allocate the bootmap. */
+ for_each_mem_cluster(memdesc, cluster, i) {
+ if (cluster->usage & 3)
+ continue;
+
+ start = cluster->start_pfn;
+ end = start + cluster->numpages;
+ if (end <= start_pfn)
+ continue;
+ if (start >= max_low_pfn)
+ continue;
+ if (start < start_pfn)
+ start = start_pfn;
+ if (end > max_low_pfn)
+ end = max_low_pfn;
+ if (end - start >= bootmap_pages) {
+ printk("allocating bootmap in area %ld:%ld\n",
+ start, start+bootmap_pages);
+ bootmap_start = start;
+ break;
+ }
+ }
+
+ if (bootmap_start == -1) {
+ max_low_pfn >>= 1;
+ printk("bootmap area not found now trying with %ld pages\n",
+ max_low_pfn);
+ goto try_again;
+ }
+
+ /* Allocate the bootmap and mark the whole MM as reserved. */
+ bootmap_size = init_bootmem(bootmap_start, max_low_pfn);
+
+ /* Mark the free regions. */
+ for_each_mem_cluster(memdesc, cluster, i) {
+ if (cluster->usage & 3)
+ continue;
+
+ start = cluster->start_pfn;
+ if (start < start_pfn)
+ start = start_pfn;
+
+ end = cluster->start_pfn + cluster->numpages;
+ if (end > max_low_pfn)
+ end = max_low_pfn;
+
+ if (start >= end)
+ continue;
+
+ start = PFN_PHYS(start);
+ end = PFN_PHYS(end);
+
+ free_bootmem(start, end - start);
+ printk("freeing pages %ld:%ld\n",
+ PFN_UP(start), PFN_DOWN(end));
+ }
+
+ /* Reserve the bootmap memory. */
+ reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size);
+ printk("reserving bootmap %ld:%ld\n", bootmap_start,
+ bootmap_start + PFN_UP(bootmap_size));
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_start = INITRD_START;
+ if (initrd_start) {
+ initrd_end = initrd_start+INITRD_SIZE;
+ printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+ (void *) initrd_start, INITRD_SIZE);
+
+ if (initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ initrd_end,
+ phys_to_virt(PFN_PHYS(max_low_pfn)));
+ initrd_start = initrd_end = 0;
+ } else {
+ reserve_bootmem(virt_to_phys(initrd_start),
+ INITRD_SIZE);
+ }
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+}
+
+int __init page_is_ram(unsigned long pfn)
+{
+ struct memclust_struct * cluster;
+ struct memdesc_struct * memdesc;
+ int i;
+
+ memdesc = (struct memdesc_struct *) (hwrpb->mddt_offset + (unsigned long) hwrpb);
+ for_each_mem_cluster(memdesc, cluster, i)
+ {
+ if (pfn >= cluster->start_pfn &&
+ pfn < cluster->start_pfn + cluster->numpages)
+ {
+ if (cluster->usage & 3)
+ return 0;
+ else
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#undef PFN_UP
+#undef PFN_DOWN
+#undef PFN_PHYS
+#undef PFN_MAX
+
+void __init
+setup_arch(char **cmdline_p)
+{
struct alpha_machine_vector *vec = NULL;
struct percpu_struct *cpu;
char *type_name, *var_name, *p;
- hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
+ hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
/*
* Locate the command line.
@@ -249,9 +419,10 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
type_name, (*var_name ? " variation " : ""), var_name,
hwrpb->sys_type, hwrpb->sys_variation);
}
- if (vec != &alpha_mv)
+ if (vec != &alpha_mv) {
alpha_mv = *vec;
-
+ }
+
#ifdef CONFIG_ALPHA_GENERIC
/* Assume that we've booted from SRM if we havn't booted from MILO.
Detect the later by looking for "MILO" in the system serial nr. */
@@ -281,29 +452,12 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
wrmces(0x7);
/* Find our memory. */
- *memory_end_p = find_end_memory();
- *memory_start_p = (unsigned long) _end;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- initrd_start = INITRD_START;
- if (initrd_start) {
- initrd_end = initrd_start+INITRD_SIZE;
- printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
- (void *) initrd_start, INITRD_SIZE);
-
- if (initrd_end > *memory_end_p) {
- printk("initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- initrd_end, (unsigned long) memory_end_p);
- initrd_start = initrd_end = 0;
- }
- }
-#endif
+ setup_memory();
/* Initialize the machine. Usually has to do with setting up
DMA windows and the like. */
if (alpha_mv.init_arch)
- alpha_mv.init_arch(memory_start_p, memory_end_p);
+ alpha_mv.init_arch();
/* Reserve standard resources. */
reserve_std_resources();
@@ -353,35 +507,6 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
#endif
}
-static unsigned long __init
-find_end_memory(void)
-{
- int i;
- unsigned long high = 0;
- struct memclust_struct * cluster;
- struct memdesc_struct * memdesc;
-
- memdesc = (struct memdesc_struct *)
- (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
- cluster = memdesc->cluster;
-
- for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
- unsigned long tmp;
- tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
- if (tmp > high)
- high = tmp;
- }
-
- /* Round it up to an even number of pages. */
- high = (high + PAGE_SIZE) & (PAGE_MASK*2);
-
- /* Enforce maximum of 2GB even if there is more. Blah. */
- if (high > 0x80000000UL)
- high = 0x80000000UL;
- return PAGE_OFFSET + high;
-}
-
-
static char sys_unknown[] = "Unknown";
static char systype_names[][16] = {
"0",
@@ -391,11 +516,13 @@ static char systype_names[][16] = {
"Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
"Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
"Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
- "Tsunami", "Wildfire", "CUSCO"
+ "Tsunami", "Wildfire", "CUSCO", "Eiger"
};
static char unofficial_names[][8] = {"100", "Ruffian"};
+static char api_names[][16] = {"200", "Nautilus"};
+
static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164", "RX164"};
static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3,4};
@@ -419,7 +546,6 @@ static char tsunami_names[][16] = {
};
static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8};
-
static struct alpha_machine_vector * __init
get_sysvec(long type, long variation, long cpu)
{
@@ -462,6 +588,7 @@ get_sysvec(long type, long variation, long cpu)
NULL, /* Tsunami -- see variation. */
NULL, /* Wildfire */
NULL, /* CUSCO */
+ &eiger_mv, /* Eiger */
};
static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata =
@@ -470,6 +597,12 @@ get_sysvec(long type, long variation, long cpu)
&ruffian_mv,
};
+ static struct alpha_machine_vector *api_vecs[] __initlocaldata =
+ {
+ NULL, /* 200 */
+ &nautilus_mv,
+ };
+
static struct alpha_machine_vector *alcor_vecs[] __initlocaldata =
{
&alcor_mv, &xlt_mv, &xlt_mv
@@ -518,6 +651,9 @@ get_sysvec(long type, long variation, long cpu)
vec = NULL;
if (type < N(systype_vecs)) {
vec = systype_vecs[type];
+ } else if ((type > ST_API_BIAS) &&
+ (type - ST_API_BIAS) < N(api_vecs)) {
+ vec = api_vecs[type - ST_API_BIAS];
} else if ((type > ST_UNOFFICIAL_BIAS) &&
(type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) {
vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
@@ -591,12 +727,14 @@ get_sysvec_byname(const char *name)
&eb64p_mv,
&eb66_mv,
&eb66p_mv,
+ &eiger_mv,
&jensen_mv,
&lx164_mv,
&miata_mv,
&mikasa_mv,
&mikasa_primo_mv,
&monet_mv,
+ &nautilus_mv,
&noname_mv,
&noritake_mv,
&noritake_primo_mv,
@@ -637,6 +775,9 @@ get_sysnames(long type, long variation,
else set type name to family */
if (type < N(systype_names)) {
*type_name = systype_names[type];
+ } else if ((type > ST_API_BIAS) &&
+ (type - ST_API_BIAS) < N(api_names)) {
+ *type_name = api_names[type - ST_API_BIAS];
} else if ((type > ST_UNOFFICIAL_BIAS) &&
(type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) {
*type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index cd8f6e0ad..cc5d8b16b 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -688,6 +688,7 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index e35dd7c7e..3fbf11495 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/irq.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
@@ -23,14 +24,15 @@
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
+#include <asm/mmu_context.h>
#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>
#include "proto.h"
-#include "irq_impl.h"
#define DEBUG_SMP 0
@@ -45,8 +47,8 @@ struct cpuinfo_alpha cpu_data[NR_CPUS];
/* A collection of single bit ipi messages. */
static struct {
- unsigned long bits __cacheline_aligned;
-} ipi_data[NR_CPUS];
+ unsigned long bits ____cacheline_aligned;
+} ipi_data[NR_CPUS] __cacheline_aligned;
enum ipi_message_type {
IPI_RESCHEDULE,
@@ -54,7 +56,7 @@ enum ipi_message_type {
IPI_CPU_STOP,
};
-spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
/* Set to a secondary's cpuid when it comes online. */
static unsigned long smp_secondary_alive;
@@ -394,6 +396,16 @@ started:
return 0;
}
+static int __init fork_by_hand(void)
+{
+ struct pt_regs regs;
+ /*
+ * don't care about the regs settings since
+ * we'll never reschedule the forked task.
+ */
+ return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
+}
+
/*
* Bring one cpu online.
*/
@@ -407,18 +419,25 @@ smp_boot_one_cpu(int cpuid, int cpunum)
to kernel_thread is irrelevant -- it's going to start where
HWRPB.CPU_restart says to start. But this gets all the other
task-y sort of data structures set up like we wish. */
- kernel_thread((void *)__smp_callin, NULL, CLONE_PID|CLONE_VM);
+ /*
+ * We can't use kernel_thread since we must avoid to
+ * reschedule the child.
+ */
+ if (fork_by_hand() < 0)
+ panic("failed fork for CPU %d", cpuid);
idle = init_task.prev_task;
if (!idle)
- panic("No idle process for CPU %d", cpunum);
- del_from_runqueue(idle);
- init_tasks[cpunum] = idle;
- idle->processor = cpuid;
+ panic("No idle process for CPU %d", cpuid);
- /* Schedule the first task manually. */
- /* ??? Ingo, what is this? */
- idle->has_cpu = 1;
+ idle->processor = cpuid;
+ __cpu_logical_map[cpunum] = cpuid;
+ cpu_number_map[cpuid] = cpunum;
+ idle->has_cpu = 1; /* we schedule the first task manually */
+
+ del_from_runqueue(idle);
+ unhash_process(idle);
+ init_tasks[cpunum] = idle;
DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
cpuid, idle->state, idle->flags));
@@ -440,13 +459,18 @@ smp_boot_one_cpu(int cpuid, int cpunum)
barrier();
}
+ /* we must invalidate our stuff as we failed to boot the CPU */
+ __cpu_logical_map[cpunum] = -1;
+ cpu_number_map[cpuid] = -1;
+
+ /* the idle task is local to us so free it as we don't use it */
+ free_task_struct(idle);
+
printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
return -1;
alive:
/* Another "Red Snapper". */
- cpu_number_map[cpuid] = cpunum;
- __cpu_logical_map[cpunum] = cpuid;
return 0;
}
@@ -579,16 +603,6 @@ smp_commence(void)
mb();
}
-/*
- * Only broken Intel needs this, thus it should not even be
- * referenced globally.
- */
-
-void __init
-initialize_secondary(void)
-{
-}
-
extern void update_one_process(struct task_struct *p, unsigned long ticks,
unsigned long user, unsigned long system,
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index fbc1b99ba..2a27bac5b 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -27,7 +27,7 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -176,15 +176,13 @@ alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
}
static void
-alcor_kill_arch(int mode, char *reboot_cmd)
+alcor_kill_arch(int mode)
{
/* Who said DEC engineer's have no sense of humor? ;-) */
if (alpha_using_srm) {
*(vuip) GRU_RESET = 0x0000dead;
mb();
}
-
- common_kill_arch(mode, reboot_cmd);
}
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index 244759d1f..bc4d2c2ba 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -31,7 +31,7 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -269,7 +269,7 @@ struct alpha_machine_vector cabriolet_mv __initmv = {
init_irq: cabriolet_init_irq,
init_pit: common_init_pit,
init_pci: cabriolet_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: cabriolet_map_irq,
pci_swizzle: common_swizzle,
};
@@ -298,7 +298,6 @@ struct alpha_machine_vector eb164_mv __initmv = {
init_irq: cabriolet_init_irq,
init_pit: common_init_pit,
init_pci: cabriolet_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: cabriolet_map_irq,
pci_swizzle: common_swizzle,
};
@@ -327,7 +326,6 @@ struct alpha_machine_vector eb66p_mv __initmv = {
init_irq: cabriolet_init_irq,
init_pit: common_init_pit,
init_pci: cabriolet_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: eb66p_map_irq,
pci_swizzle: common_swizzle,
};
@@ -356,7 +354,6 @@ struct alpha_machine_vector lx164_mv __initmv = {
init_irq: cabriolet_init_irq,
init_pit: common_init_pit,
init_pci: alphapc164_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: alphapc164_map_irq,
pci_swizzle: common_swizzle,
};
@@ -385,7 +382,6 @@ struct alpha_machine_vector pc164_mv __initmv = {
init_irq: cabriolet_init_irq,
init_pit: common_init_pit,
init_pci: alphapc164_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: alphapc164_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 9959aad33..f0ef47183 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -27,7 +27,7 @@
#include <asm/hwrpb.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -39,28 +39,30 @@
static void
dp264_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
{
- if (irq >= 16) {
- volatile unsigned long *csr;
+ volatile unsigned long *csr;
- if (TSUNAMI_bootcpu < 2)
- if (!TSUNAMI_bootcpu)
- csr = &TSUNAMI_cchip->dim0.csr;
- else
- csr = &TSUNAMI_cchip->dim1.csr;
+ if (TSUNAMI_bootcpu < 2) {
+ if (!TSUNAMI_bootcpu)
+ csr = &TSUNAMI_cchip->dim0.csr;
else
- if (TSUNAMI_bootcpu == 2)
- csr = &TSUNAMI_cchip->dim2.csr;
- else
- csr = &TSUNAMI_cchip->dim3.csr;
-
- *csr = ~mask;
- mb();
- *csr;
+ csr = &TSUNAMI_cchip->dim1.csr;
+ } else {
+ if (TSUNAMI_bootcpu == 2)
+ csr = &TSUNAMI_cchip->dim2.csr;
+ else
+ csr = &TSUNAMI_cchip->dim3.csr;
+ }
+
+ *csr = ~mask;
+ mb();
+ *csr;
+
+ if (irq < 16) {
+ if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
}
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
}
static void
@@ -274,8 +276,19 @@ dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
struct pci_controler *hose = dev->sysdata;
int irq = COMMON_TABLE_LOOKUP;
- if (irq > 0)
+ if (irq > 0) {
irq += 16 * hose->index;
+ } else {
+ /* ??? The Contaq IDE controler on the ISA bridge uses
+ "legacy" interrupts 14 and 15. I don't know if anything
+ can wind up at the same slot+pin on hose1, so we'll
+ just have to trust whatever value the console might
+ have assigned. */
+
+ u8 irq8;
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
+ irq = irq8;
+ }
return irq;
}
@@ -418,7 +431,7 @@ struct alpha_machine_vector dp264_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: _PROBE_MASK(64),
+ irq_probe_mask: TSUNAMI_PROBE_MASK,
update_irq_hw: dp264_update_irq_hw,
ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
@@ -427,7 +440,7 @@ struct alpha_machine_vector dp264_mv __initmv = {
init_irq: dp264_init_irq,
init_pit: common_init_pit,
init_pci: dp264_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: tsunami_kill_arch,
pci_map_irq: dp264_map_irq,
pci_swizzle: common_swizzle,
};
@@ -445,7 +458,7 @@ struct alpha_machine_vector monet_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: _PROBE_MASK(64),
+ irq_probe_mask: TSUNAMI_PROBE_MASK,
update_irq_hw: dp264_update_irq_hw,
ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
@@ -454,7 +467,7 @@ struct alpha_machine_vector monet_mv __initmv = {
init_irq: dp264_init_irq,
init_pit: common_init_pit,
init_pci: monet_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: tsunami_kill_arch,
pci_map_irq: monet_map_irq,
pci_swizzle: monet_swizzle,
};
@@ -471,7 +484,7 @@ struct alpha_machine_vector webbrick_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: _PROBE_MASK(64),
+ irq_probe_mask: TSUNAMI_PROBE_MASK,
update_irq_hw: dp264_update_irq_hw,
ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
@@ -479,8 +492,8 @@ struct alpha_machine_vector webbrick_mv __initmv = {
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
init_pit: common_init_pit,
- init_pci: dp264_init_pci,
- kill_arch: common_kill_arch,
+ init_pci: common_init_pci,
+ kill_arch: tsunami_kill_arch,
pci_map_irq: webbrick_map_irq,
pci_swizzle: common_swizzle,
};
@@ -497,7 +510,7 @@ struct alpha_machine_vector clipper_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: _PROBE_MASK(64),
+ irq_probe_mask: TSUNAMI_PROBE_MASK,
update_irq_hw: clipper_update_irq_hw,
ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
@@ -506,7 +519,7 @@ struct alpha_machine_vector clipper_mv __initmv = {
init_irq: clipper_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: tsunami_kill_arch,
pci_map_irq: clipper_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
index 09e0b0def..e8e224715 100644
--- a/arch/alpha/kernel/sys_eb64p.c
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -28,7 +28,7 @@
#include <asm/core_lca.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -183,7 +183,7 @@ struct alpha_machine_vector eb64p_mv __initmv = {
init_irq: eb64p_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: eb64p_map_irq,
pci_swizzle: common_swizzle,
};
@@ -212,7 +212,6 @@ struct alpha_machine_vector eb66_mv __initmv = {
init_irq: eb64p_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: eb64p_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
new file mode 100644
index 000000000..433abddfb
--- /dev/null
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -0,0 +1,215 @@
+/*
+ * linux/arch/alpha/kernel/sys_eiger.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996, 1999 Jay A Estabrook
+ * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1999 Iain Grant
+ *
+ * Code supporting the EIGER (EV6+TSUNAMI).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/pgtable.h>
+#include <asm/core_tsunami.h>
+#include <asm/hwrpb.h>
+
+#include "proto.h"
+#include <asm/hw_irq.h>
+#include "pci_impl.h"
+#include "machvec_impl.h"
+
+
+/*
+ * HACK ALERT! only the boot cpu is used for interrupts.
+ */
+
+static void
+eiger_update_irq_hw(unsigned long irq, unsigned long unused, int unmask_p)
+{
+ unsigned int regaddr;
+ unsigned long mask;
+
+ if (irq <= 15) {
+ if (irq <= 7)
+ outb(alpha_irq_mask, 0x21); /* ISA PIC1 */
+ else
+ outb(alpha_irq_mask >> 8, 0xA1); /* ISA PIC2 */
+ } else {
+ if (irq > 63)
+ mask = _alpha_irq_masks[1] << 16;
+ else
+ mask = _alpha_irq_masks[0] >> ((irq - 16) & 0x30);
+
+ regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
+
+ outl(mask & 0xffff0000UL, regaddr);
+ }
+}
+
+static void
+eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ unsigned intstatus;
+
+ /*
+ * The PALcode will have passed us vectors 0x800 or 0x810,
+ * which are fairly arbitrary values and serve only to tell
+ * us whether an interrupt has come in on IRQ0 or IRQ1. If
+ * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
+ * probably ISA, but PCI interrupts can come through IRQ0
+ * as well if the interrupt controller isn't in accelerated
+ * mode.
+ *
+ * OTOH, the accelerator thing doesn't seem to be working
+ * overly well, so what we'll do instead is try directly
+ * examining the Master Interrupt Register to see if it's a
+ * PCI interrupt, and if _not_ then we'll pass it on to the
+ * ISA handler.
+ */
+
+ intstatus = inw(0x500) & 15;
+ if (intstatus) {
+ /*
+ * This is a PCI interrupt. Check each bit and
+ * despatch an interrupt if it's set.
+ */
+
+ if (intstatus & 8) handle_irq(16+3, 16+3, regs);
+ if (intstatus & 4) handle_irq(16+2, 16+2, regs);
+ if (intstatus & 2) handle_irq(16+1, 16+1, regs);
+ if (intstatus & 1) handle_irq(16+0, 16+0, regs);
+ } else {
+ isa_device_interrupt (vector, regs);
+ }
+}
+
+static void
+eiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq = (vector - 0x800) >> 4;
+ handle_irq(irq, irq, regs);
+}
+
+static void __init
+eiger_init_irq(void)
+{
+ outb(0, DMA1_RESET_REG);
+ outb(0, DMA2_RESET_REG);
+ outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
+ outb(0, DMA2_MASK_REG);
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = eiger_srm_device_interrupt;
+
+ eiger_update_irq_hw(16, alpha_irq_mask, 0);
+
+ enable_irq(2);
+}
+
+static int __init
+eiger_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ u8 irq_orig;
+
+ /* The SRM console has already calculated out the IRQ value's for
+ option cards. As this works lets just read in the value already
+ set and change it to a useable value by Linux.
+
+ All the IRQ values generated by the console are greater than 90,
+ so we subtract 80 because it is (90 - allocated ISA IRQ's). */
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_orig);
+
+ return irq_orig - 0x80;
+}
+
+static u8 __init
+eiger_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ struct pci_controler *hose = dev->sysdata;
+ int slot, pin = *pinp;
+ int bridge_count = 0;
+
+ /* Find the number of backplane bridges. */
+ int backplane = inw(0x502) & 0x0f;
+
+ switch (backplane)
+ {
+ case 0x00: bridge_count = 0; break; /* No bridges */
+ case 0x01: bridge_count = 1; break; /* 1 */
+ case 0x03: bridge_count = 2; break; /* 2 */
+ case 0x07: bridge_count = 3; break; /* 3 */
+ case 0x0f: bridge_count = 4; break; /* 4 */
+ };
+
+ /* Check first for the built-in bridges on hose 0. */
+ if (hose->index == 0
+ && PCI_SLOT(dev->bus->self->devfn) > 20-bridge_count) {
+ slot = PCI_SLOT(dev->devfn);
+ } else {
+ /* Must be a card-based bridge. */
+ do {
+ /* Check for built-in bridges on hose 0. */
+ if (hose->index == 0
+ && (PCI_SLOT(dev->bus->self->devfn)
+ > 20 - bridge_count)) {
+ slot = PCI_SLOT(dev->devfn);
+ break;
+ }
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ /* Slot of the next bridge. */
+ slot = PCI_SLOT(dev->devfn);
+ } while (dev->bus->self);
+ }
+ *pinp = pin;
+ return slot;
+}
+
+/*
+ * The System Vectors
+ */
+
+struct alpha_machine_vector eiger_mv __initmv = {
+ vector_name: "Eiger",
+ DO_EV6_MMU,
+ DO_DEFAULT_RTC,
+ DO_TSUNAMI_IO,
+ DO_TSUNAMI_BUS,
+ machine_check: tsunami_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
+
+ nr_irqs: 128,
+ irq_probe_mask: TSUNAMI_PROBE_MASK,
+ update_irq_hw: eiger_update_irq_hw,
+ ack_irq: common_ack_irq,
+ device_interrupt: eiger_device_interrupt,
+
+ init_arch: tsunami_init_arch,
+ init_irq: eiger_init_irq,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: tsunami_kill_arch,
+ pci_map_irq: eiger_map_irq,
+ pci_swizzle: eiger_swizzle,
+};
+ALIAS_MV(eiger)
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index 0380574a8..ad156c9f2 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -28,7 +28,7 @@
#include <asm/pgtable.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "machvec_impl.h"
@@ -140,6 +140,6 @@ struct alpha_machine_vector jensen_mv __initmv = {
init_irq: jensen_init_irq,
init_pit: common_init_pit,
init_pci: NULL,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
};
ALIAS_MV(jensen)
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index 0bea4e3dd..b2da23528 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -25,7 +25,7 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -274,14 +274,13 @@ miata_init_pci(void)
}
static void
-miata_kill_arch (int mode, char *reboot_cmd)
+miata_kill_arch(int mode)
{
/* Who said DEC engineers have no sense of humor? ;-) */
if (alpha_using_srm) {
*(vuip) PYXIS_RESET = 0x0000dead;
mb();
}
- common_kill_arch(mode, reboot_cmd);
}
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index 0c08d9fc0..ac55371a6 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -28,7 +28,7 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -194,7 +194,7 @@ struct alpha_machine_vector mikasa_mv __initmv = {
init_irq: mikasa_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: mikasa_map_irq,
pci_swizzle: common_swizzle,
};
@@ -223,7 +223,6 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
init_irq: mikasa_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: mikasa_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
new file mode 100644
index 000000000..b51eee671
--- /dev/null
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -0,0 +1,535 @@
+/*
+ * linux/arch/alpha/kernel/sys_nautilus.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1999 Alpha Processor, Inc.,
+ * (David Daniel, Stig Telfer, Soohoon Lee)
+ *
+ * Code supporting NAUTILUS systems.
+ *
+ *
+ * NAUTILUS has the following I/O features:
+ *
+ * a) Driven by AMD 751 aka IRONGATE (northbridge):
+ * 4 PCI slots
+ * 1 AGP slot
+ *
+ * b) Driven by ALI M1543C (southbridge)
+ * 2 ISA slots
+ * 2 IDE connectors
+ * 1 dual drive capable FDD controller
+ * 2 serial ports
+ * 1 ECP/EPP/SP parallel port
+ * 2 USB ports
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/reboot.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/pgtable.h>
+#include <asm/core_irongate.h>
+#include <asm/hwrpb.h>
+
+#include "proto.h"
+#include <asm/hw_irq.h>
+#include "pci_impl.h"
+#include "machvec_impl.h"
+
+#define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index)
+
+static void
+nautilus_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ /* The timer is connected to PIC interrupt line also on Nautilus.
+ The timer interrupt handler enables the PIC line, so in order
+ not to get multiple timer interrupt sources, we mask it out
+ at all times. */
+
+ mask |= 0x100;
+ if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void __init
+nautilus_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ enable_irq(2); /* enable cascade */
+ disable_irq(8);
+}
+
+static int __init
+nautilus_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ /* Preserve the IRQ set up by the console. */
+
+ u8 irq;
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+ return irq;
+}
+
+void
+nautilus_kill_arch(int mode)
+{
+ u8 tmp;
+
+ if (mode == LINUX_REBOOT_CMD_RESTART) {
+ pcibios_read_config_byte(0, 0x38, 0x43, &tmp);
+ pcibios_write_config_byte(0, 0x38, 0x43, tmp | 0x80);
+ outb(1, 0x92);
+ outb(0, 0x92);
+ }
+}
+
+/* Machine check handler code
+ *
+ * Perform analysis of a machine check that was triggered by the EV6
+ * CPU's fault-detection mechanism.
+ */
+
+/* IPR structures for EV6, containing the necessary data for the
+ * machine check handler to unpick the logout frame
+ */
+
+/* I_STAT */
+
+#define EV6__I_STAT__PAR ( 1 << 29 )
+
+/* MM_STAT */
+
+#define EV6__MM_STAT__DC_TAG_PERR ( 1 << 10 )
+
+/* DC_STAT */
+
+#define EV6__DC_STAT__SEO ( 1 << 4 )
+#define EV6__DC_STAT__ECC_ERR_LD ( 1 << 3 )
+#define EV6__DC_STAT__ECC_ERR_ST ( 1 << 2 )
+#define EV6__DC_STAT__TPERR_P1 ( 1 << 1 )
+#define EV6__DC_STAT__TPERR_P0 ( 1 )
+
+/* C_STAT */
+
+#define EV6__C_STAT__BC_PERR ( 0x01 )
+#define EV6__C_STAT__DC_PERR ( 0x02 )
+#define EV6__C_STAT__DSTREAM_MEM_ERR ( 0x03 )
+#define EV6__C_STAT__DSTREAM_BC_ERR ( 0x04 )
+#define EV6__C_STAT__DSTREAM_DC_ERR ( 0x05 )
+#define EV6__C_STAT__PROBE_BC_ERR0 ( 0x06 )
+#define EV6__C_STAT__PROBE_BC_ERR1 ( 0x07 )
+#define EV6__C_STAT__ISTREAM_MEM_ERR ( 0x0B )
+#define EV6__C_STAT__ISTREAM_BC_ERR ( 0x0C )
+#define EV6__C_STAT__DSTREAM_MEM_DBL ( 0x13 )
+#define EV6__C_STAT__DSTREAM_BC_DBL ( 0x14 )
+#define EV6__C_STAT__ISTREAM_MEM_DBL ( 0x1B )
+#define EV6__C_STAT__ISTREAM_BC_DBL ( 0x1C )
+
+
+/* Take the two syndromes from the CBOX error chain and convert them
+ * into a bit number. */
+
+/* NOTE - since I don't know of any difference between C0 and C1 I
+ just ignore C1, since in all cases I've seen so far they are
+ identical. */
+
+static const unsigned char ev6_bit_to_syndrome[72] =
+{
+ 0xce, 0xcb, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, /* 0 */
+ 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34, /* 8 */
+ 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, /* 16 */
+ 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xf1, 0xf4, /* 24 */
+ 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, /* 32 */
+ 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xb0, 0xb5, /* 40 */
+ 0x8f, 0x8a, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, /* 48 */
+ 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75, /* 56 */
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 /* 64 */
+};
+
+
+static int ev6_syn2bit(unsigned long c0, unsigned long c1)
+{
+ int bit;
+
+ for (bit = 0; bit < 72; bit++)
+ if (ev6_bit_to_syndrome[bit] == c0) return bit;
+ for (bit = 0; bit < 72; bit++)
+ if (ev6_bit_to_syndrome[bit] == c1) return bit + 64;
+
+ return -1; /* not found */
+}
+
+
+/* Single bit ECC errors are categorized here. */
+
+#if 0
+static const char *interr = "CPU internal error";
+static const char *slotb= "Slot-B error";
+static const char *membus= "Memory/EV6-bus error";
+#else
+static const char *interr = "";
+static const char *slotb = "";
+static const char *membus = "";
+#endif
+
+static void
+ev6_crd_interp(char *interp, struct el_common_EV6_mcheck * L)
+{
+ /* Icache data or tag parity error. */
+ if (L->I_STAT & EV6__I_STAT__PAR) {
+ sprintf(interp, "%s: I_STAT[PAR]\n "
+ "Icache data or tag parity error", interr);
+ return;
+ }
+
+ /* Dcache tag parity error (on issue) (DFAULT). */
+ if (L->MM_STAT & EV6__MM_STAT__DC_TAG_PERR) {
+ sprintf(interp, "%s: MM_STAT[DC_TAG_PERR]\n "
+ "Dcache tag parity error(on issue)", interr);
+ return;
+ }
+
+ /* Errors relating to D-stream set non-zero DC_STAT.
+ Mask CRD bits. */
+ switch (L->DC_STAT & (EV6__DC_STAT__ECC_ERR_ST
+ | EV6__DC_STAT__ECC_ERR_LD)) {
+ case EV6__DC_STAT__ECC_ERR_ST:
+ /* Dcache single-bit ECC error on small store */
+ sprintf(interp, "%s: DC_STAT[ECC_ERR_ST]\n "
+ "Dcache single-bit ECC error on small store", interr);
+ return;
+
+ case EV6__DC_STAT__ECC_ERR_LD:
+ switch (L->C_STAT) {
+ case 0:
+ /* Dcache single-bit error on speculative load */
+ /* Bcache victim read on Dcache/Bcache miss */
+ sprintf(interp, "%s: DC_STAT[ECC_ERR_LD] C_STAT=0\n "
+ "Dcache single-bit ECC error on speculative load",
+ slotb);
+ return;
+
+ case EV6__C_STAT__DSTREAM_DC_ERR:
+ /* Dcache single bit error on load */
+ sprintf(interp, "%s: DC_STAT[ECC_ERR_LD] C_STAT[DSTREAM_DC_ERR]\n"
+ " Dcache single-bit ECC error on speculative load, bit %d",
+ interr, ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
+ return;
+
+ case EV6__C_STAT__DSTREAM_BC_ERR:
+ /* Bcache single-bit error on Dcache fill */
+ sprintf(interp, "%s: DC_STAT[ECC_ERR_LD] C_STAT[DSTREAM_BC_ERR]\n"
+ " Bcache single-bit error on Dcache fill, bit %d",
+ slotb, ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
+ return;
+
+ case EV6__C_STAT__DSTREAM_MEM_ERR:
+ /* Memory single-bit error on Dcache fill */
+ sprintf(interp, "%s (to Dcache): DC_STAT[ECC_ERR_LD] "
+ "C_STAT[DSTREAM_MEM_ERR]\n "
+ "Memory single-bit error on Dcache fill, "
+ "Address 0x%lX, bit %d",
+ membus, L->C_ADDR, ev6_syn2bit(L->DC0_SYNDROME,
+ L->DC1_SYNDROME));
+ return;
+ }
+ }
+
+ /* I-stream, other misc errors go on C_STAT alone */
+ switch (L->C_STAT) {
+ case EV6__C_STAT__ISTREAM_BC_ERR:
+ /* Bcache single-bit error on Icache fill (also MCHK) */
+ sprintf(interp, "%s: C_STAT[ISTREAM_BC_ERR]\n "
+ "Bcache single-bit error on Icache fill, bit %d",
+ slotb, ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
+ return;
+
+ case EV6__C_STAT__ISTREAM_MEM_ERR:
+ /* Memory single-bit error on Icache fill (also MCHK) */
+ sprintf(interp, "%s : C_STATISTREAM_MEM_ERR]\n "
+ "Memory single-bit error on Icache fill "
+ "addr 0x%lX, bit %d",
+ membus, L->C_ADDR, ev6_syn2bit(L->DC0_SYNDROME,
+ L->DC1_SYNDROME));
+ return;
+
+ case EV6__C_STAT__PROBE_BC_ERR0:
+ case EV6__C_STAT__PROBE_BC_ERR1:
+ /* Bcache single-bit error on a probe hit */
+ sprintf(interp, "%s: C_STAT[PROBE_BC_ERR]\n "
+ "Bcache single-bit error on a probe hit, "
+ "addr 0x%lx, bit %d",
+ slotb, L->C_ADDR, ev6_syn2bit(L->DC0_SYNDROME,
+ L->DC1_SYNDROME));
+ return;
+ }
+}
+
+static void
+ev6_mchk_interp(char *interp, struct el_common_EV6_mcheck * L)
+{
+ /* Machine check errors described by DC_STAT */
+ switch (L->DC_STAT) {
+ case EV6__DC_STAT__TPERR_P0:
+ case EV6__DC_STAT__TPERR_P1:
+ /* Dcache tag parity error (on retry) */
+ sprintf(interp, "%s: DC_STAT[TPERR_P0|TPERR_P1]\n "
+ "Dcache tag parity error(on retry)", interr);
+ return;
+
+ case EV6__DC_STAT__SEO:
+ /* Dcache second error on store */
+ sprintf(interp, "%s: DC_STAT[SEO]\n "
+ "Dcache second error during mcheck", interr);
+ return;
+ }
+
+ /* Machine check errors described by C_STAT */
+ switch (L->C_STAT) {
+ case EV6__C_STAT__DC_PERR:
+ /* Dcache duplicate tag parity error */
+ sprintf(interp, "%s: C_STAT[DC_PERR]\n "
+ "Dcache duplicate tag parity error at 0x%lX",
+ interr, L->C_ADDR);
+ return;
+
+ case EV6__C_STAT__BC_PERR:
+ /* Bcache tag parity error */
+ sprintf(interp, "%s: C_STAT[BC_PERR]\n "
+ "Bcache tag parity error at 0x%lX",
+ slotb, L->C_ADDR);
+ return;
+
+ case EV6__C_STAT__ISTREAM_BC_ERR:
+ /* Bcache single-bit error on Icache fill (also CRD) */
+ sprintf(interp, "%s: C_STAT[ISTREAM_BC_ERR]\n "
+ "Bcache single-bit error on Icache fill 0x%lX bit %d",
+ slotb, L->C_ADDR,
+ ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
+ return;
+
+
+ case EV6__C_STAT__ISTREAM_MEM_ERR:
+ /* Memory single-bit error on Icache fill (also CRD) */
+ sprintf(interp, "%s: C_STAT[ISTREAM_MEM_ERR]\n "
+ "Memory single-bit error on Icache fill 0x%lX, bit %d",
+ membus, L->C_ADDR,
+ ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
+ return;
+
+
+ case EV6__C_STAT__ISTREAM_BC_DBL:
+ /* Bcache double-bit error on Icache fill */
+ sprintf(interp, "%s: C_STAT[ISTREAM_BC_DBL]\n "
+ "Bcache double-bit error on Icache fill at 0x%lX",
+ slotb, L->C_ADDR);
+ return;
+ case EV6__C_STAT__DSTREAM_BC_DBL:
+ /* Bcache double-bit error on Dcache fill */
+ sprintf(interp, "%s: C_STAT[DSTREAM_BC_DBL]\n "
+ "Bcache double-bit error on Dcache fill at 0x%lX",
+ slotb, L->C_ADDR);
+ return;
+
+ case EV6__C_STAT__ISTREAM_MEM_DBL:
+ /* Memory double-bit error on Icache fill */
+ sprintf(interp, "%s: C_STAT[ISTREAM_MEM_DBL]\n "
+ "Memory double-bit error on Icache fill at 0x%lX",
+ membus, L->C_ADDR);
+ return;
+
+ case EV6__C_STAT__DSTREAM_MEM_DBL:
+ /* Memory double-bit error on Dcache fill */
+ sprintf(interp, "%s: C_STAT[DSTREAM_MEM_DBL]\n "
+ "Memory double-bit error on Dcache fill at 0x%lX",
+ membus, L->C_ADDR);
+ return;
+ }
+}
+
+static void
+ev6_cpu_machine_check(unsigned long vector, struct el_common_EV6_mcheck *L,
+ struct pt_regs *regs)
+{
+ char interp[80];
+
+ /* This is verbose and looks intimidating. Should it be printed for
+ corrected (CRD) machine checks? */
+
+ printk(KERN_CRIT "PALcode logout frame: "
+ "MCHK_Code %d "
+ "MCHK_Frame_Rev %d\n"
+ "I_STAT %016lx "
+ "DC_STAT %016lx "
+ "C_ADDR %016lx\n"
+ "SYND1 %016lx "
+ "SYND0 %016lx "
+ "C_STAT %016lx\n"
+ "C_STS %016lx "
+ "RES %016lx "
+ "EXC_ADDR%016lx\n"
+ "IER_CM %016lx "
+ "ISUM %016lx "
+ "MM_STAT %016lx\n"
+ "PALBASE %016lx "
+ "I_CTL %016lx "
+ "PCTX %016lx\n"
+ "CPU registers: "
+ "PC %016lx "
+ "Return %016lx\n",
+ L->MCHK_Code, L->MCHK_Frame_Rev, L->I_STAT, L->DC_STAT,
+ L->C_ADDR, L->DC1_SYNDROME, L->DC0_SYNDROME, L->C_STAT,
+ L->C_STS, L->RESERVED0, L->EXC_ADDR, L->IER_CM, L->ISUM,
+ L->MM_STAT, L->PAL_BASE, L->I_CTL, L->PCTX,
+ regs->pc, regs->r26);
+
+ /* Attempt an interpretation on the meanings of the fields above. */
+ sprintf(interp, "No interpretation available!" );
+ if (vector == SCB_Q_PROCERR)
+ ev6_crd_interp(interp, L);
+ else if (vector == SCB_Q_PROCMCHK)
+ ev6_mchk_interp(interp, L);
+
+ printk(KERN_CRIT "interpretation: %s\n\n", interp);
+}
+
+
+/* Perform analysis of a machine check that arrived from the system (NMI) */
+
+static void
+naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs *regs)
+{
+ printk("xtime %lx\n", CURRENT_TIME);
+ printk("PC %lx RA %lx\n", regs->pc, regs->r26);
+ irongate_pci_clr_err();
+}
+
+/* Machine checks can come from two sources - those on the CPU and those
+ in the system. They are analysed separately but all starts here. */
+
+void
+nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs *regs)
+{
+ char *mchk_class;
+ unsigned cpu_analysis=0, sys_analysis=0;
+
+ /* Now for some analysis. Machine checks fall into two classes --
+ those picked up by the system, and those picked up by the CPU.
+ Add to that the two levels of severity - correctable or not. */
+
+ if (vector == SCB_Q_SYSMCHK
+ && ((IRONGATE0->dramms & 0x3FF) == 0x300)) {
+ unsigned long nmi_ctl, temp;
+
+ /* Clear ALI NMI */
+ nmi_ctl = inb(0x61);
+ nmi_ctl |= 0x0c;
+ outb(nmi_ctl, 0x61);
+ nmi_ctl &= ~0x0c;
+ outb(nmi_ctl, 0x61);
+
+ temp = IRONGATE0->stat_cmd;
+ IRONGATE0->stat_cmd = temp; /* write again clears error bits */
+ mb();
+ temp = IRONGATE0->stat_cmd; /* re-read to force write */
+
+ temp = IRONGATE0->dramms;
+ IRONGATE0->dramms = temp; /* write again clears error bits */
+ mb();
+ temp = IRONGATE0->dramms; /* re-read to force write */
+
+ draina();
+ wrmces(0x7);
+ mb();
+ return;
+ }
+
+ switch (vector) {
+ case SCB_Q_SYSERR:
+ mchk_class = "Correctable System Machine Check (NMI)";
+ sys_analysis = 1;
+ break;
+ case SCB_Q_SYSMCHK:
+ mchk_class = "Fatal System Machine Check (NMI)";
+ sys_analysis = 1;
+ break;
+
+ case SCB_Q_PROCERR:
+ mchk_class = "Correctable Processor Machine Check";
+ cpu_analysis = 1;
+ break;
+ case SCB_Q_PROCMCHK:
+ mchk_class = "Fatal Processor Machine Check";
+ cpu_analysis = 1;
+ break;
+
+ default:
+ mchk_class = "Unknown vector!";
+ break;
+ }
+
+ printk(KERN_CRIT "NAUTILUS Machine check 0x%lx [%s]\n",
+ vector, mchk_class);
+
+ if (cpu_analysis)
+ ev6_cpu_machine_check(vector,
+ (struct el_common_EV6_mcheck *)la_ptr,
+ regs);
+ if (sys_analysis)
+ naut_sys_machine_check(vector, la_ptr, regs);
+
+ /* Tell the PALcode to clear the machine check */
+ draina();
+ wrmces(0x7);
+ mb();
+}
+
+
+
+/*
+ * The System Vectors
+ */
+
+struct alpha_machine_vector nautilus_mv __initmv = {
+ vector_name: "Nautilus",
+ DO_EV6_MMU,
+ DO_DEFAULT_RTC,
+ DO_IRONGATE_IO,
+ DO_IRONGATE_BUS,
+ machine_check: nautilus_machine_check,
+ max_dma_address: ALPHA_NAUTILUS_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
+
+ nr_irqs: 16,
+ irq_probe_mask: (_PROBE_MASK(16) & ~0x101UL),
+ update_irq_hw: nautilus_update_irq_hw,
+ ack_irq: common_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: irongate_init_arch,
+ init_irq: nautilus_init_irq,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: nautilus_kill_arch,
+ pci_map_irq: nautilus_map_irq,
+ pci_swizzle: common_swizzle,
+};
+ALIAS_MV(nautilus)
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index adce91de2..c1a793393 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -29,7 +29,7 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -254,7 +254,7 @@ struct alpha_machine_vector noritake_mv __initmv = {
init_irq: noritake_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: noritake_map_irq,
pci_swizzle: noritake_swizzle,
};
@@ -283,7 +283,6 @@ struct alpha_machine_vector noritake_primo_mv __initmv = {
init_irq: noritake_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: noritake_map_irq,
pci_swizzle: noritake_swizzle,
};
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index 4561c4046..0a0ce2267 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -25,46 +25,59 @@
#include <asm/core_mcpcia.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
+static unsigned int hose_irq_masks[4] = {
+ 0xff0000, 0xfe0000, 0xff0000, 0xff0000
+};
+
+
+/* Note that `mask' initially contains only the low 64 bits. */
static void
rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
{
- if (irq >= 40) {
- /* PCI bus 1 with builtin NCR810 SCSI */
- *(vuip)MCPCIA_INT_MASK0(5) =
- (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(5);
+ unsigned int saddle, hose, new_irq;
+
+ if (irq < 16) {
+ if (irq < 8)
+ outb(mask, 0x21); /* ISA PIC1 */
+ else
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ return;
}
- else if (irq >= 16) {
- /* PCI bus 0 with EISA bridge */
- *(vuip)MCPCIA_INT_MASK0(4) =
- (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(4);
+
+ saddle = (irq > 63);
+ mask = _alpha_irq_masks[saddle];
+
+ if (saddle == 0) {
+ /* Saddle 0 includes EISA interrupts. */
+ mask >>= 16;
+ new_irq = irq - 16;
+ } else {
+ new_irq = irq - 64;
+ }
+
+ hose = saddle << 1;
+ if (new_irq >= 24) {
+ mask >>= 24;
+ hose += 1;
}
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
+
+ *(vuip)MCPCIA_INT_MASK0(hose) =
+ (~mask & 0x00ffffff) | hose_irq_masks[hose];
+ mb();
+ *(vuip)MCPCIA_INT_MASK0(hose);
}
static void
rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
-
- ack = irq = (vector - 0x800) >> 4;
+ int irq;
- /* ??? A 4 bus RAWHIDE has 67 interrupts. Oops. We need
- something wider than one word for our own internal
- manipulations. */
+ irq = (vector - 0x800) >> 4;
/*
* The RAWHIDE SRM console reports PCI interrupts with a vector
@@ -73,37 +86,37 @@ rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
* it line up with the actual bit numbers from the REQ registers,
* which is how we manage the interrupts/mask. Sigh...
*
- * also, PCI #1 interrupts are offset some more... :-(
+ * Also, PCI #1 interrupts are offset some more... :-(
*/
- if (irq == 52)
- ack = irq = 56; /* SCSI on PCI 1 is special */
- else {
- if (irq >= 24) /* adjust all PCI interrupts down 8 */
- ack = irq = irq - 8;
- if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */
- ack = irq = irq - 8;
+
+ if (irq == 52) {
+ /* SCSI on PCI1 is special. */
+ irq = 72;
}
- handle_irq(irq, ack, regs);
+ /* Adjust by which hose it is from. */
+ irq -= ((irq + 16) >> 2) & 0x38;
+
+ handle_irq(irq, irq, regs);
}
static void __init
rawhide_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ struct pci_controler *hose;
- /* HACK ALERT! only PCI busses 0 and 1 are used currently,
- (MIDs 4 and 5 respectively) and routing is only to CPU #1*/
+ mcpcia_init_hoses();
- *(vuip)MCPCIA_INT_MASK0(4) =
- (~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(4);
+ STANDARD_INIT_IRQ_PROLOG;
+
+ /* HACK ALERT! Routing is only to CPU #0. */
+ for (hose = hose_head; hose; hose = hose->next) {
+ int h = hose->index;
- *(vuip)MCPCIA_INT_MASK0(5) =
- (~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(5);
+ *(vuip)MCPCIA_INT_MASK0(h) = hose_irq_masks[h];
+ mb();
+ *(vuip)MCPCIA_INT_MASK0(h);
+ }
enable_irq(2);
}
@@ -177,8 +190,8 @@ struct alpha_machine_vector rawhide_mv __initmv = {
min_io_address: DEFAULT_IO_BASE,
min_mem_address: MCPCIA_DEFAULT_MEM_BASE,
- nr_irqs: 64,
- irq_probe_mask: _PROBE_MASK(64),
+ nr_irqs: 128,
+ irq_probe_mask: _PROBE_MASK(128),
update_irq_hw: rawhide_update_irq_hw,
ack_irq: common_ack_irq,
device_interrupt: rawhide_srm_device_interrupt,
@@ -187,7 +200,7 @@ struct alpha_machine_vector rawhide_mv __initmv = {
init_irq: rawhide_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: rawhide_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index f303a8255..c03a91296 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -26,7 +26,7 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -212,15 +212,14 @@ ruffian_init_pit (void)
}
static void
-ruffian_kill_arch (int mode, char *reboot_cmd)
+ruffian_kill_arch (int mode)
{
#if 0
- /* this only causes re-entry to ARCSBIOS */
+ /* This only causes re-entry to ARCSBIOS */
/* Perhaps this works for other PYXIS as well? */
*(vuip) PYXIS_RESET = 0x0000dead;
mb();
#endif
- common_kill_arch(mode, reboot_cmd);
}
static int __init
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
index c6a4ac5b3..969d3561f 100644
--- a/arch/alpha/kernel/sys_rx164.c
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -26,7 +26,7 @@
#include <asm/core_polaris.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -229,7 +229,7 @@ struct alpha_machine_vector rx164_mv __initmv = {
init_irq: rx164_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: rx164_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index 86b1d8371..53afe259b 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -26,7 +26,7 @@
#include <asm/core_t2.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -248,7 +248,7 @@ struct alpha_machine_vector sable_mv __initmv = {
init_irq: sable_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: sable_map_irq,
pci_swizzle: common_swizzle,
@@ -283,7 +283,6 @@ struct alpha_machine_vector sable_gamma_mv __initmv = {
init_irq: sable_init_irq,
init_pit: common_init_pit,
init_pci: common_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: sable_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index a6575de9c..f26991f55 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -30,7 +30,7 @@
#include <asm/core_lca.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -55,7 +55,7 @@ sio_init_irq(void)
}
static inline void __init
-xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+xl_init_arch(void)
{
struct pci_controler *hose;
@@ -93,7 +93,7 @@ xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* Create our single hose.
*/
- hose = alloc_pci_controler(mem_start);
+ hose = alloc_pci_controler();
hose->io_space = &ioport_resource;
hose->mem_space = &iomem_resource;
hose->config_space = LCA_CONF;
@@ -101,7 +101,7 @@ xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
}
static inline void __init
-alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+alphabook1_init_arch(void)
{
/* The AlphaBook1 has LCD video fixed at 800x600,
37 rows and 100 cols. */
@@ -109,7 +109,7 @@ alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end)
screen_info.orig_video_cols = 100;
screen_info.orig_video_lines = 37;
- lca_init_arch(mem_start, mem_end);
+ lca_init_arch();
}
@@ -238,8 +238,8 @@ p2k_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
static inline void __init
noname_init_pci(void)
{
- sio_pci_route();
common_init_pci();
+ sio_pci_route();
sio_fixup_irq_levels(sio_collect_irq_levels());
ns87312_enable_ide(0x26e);
}
@@ -250,8 +250,8 @@ alphabook1_init_pci(void)
struct pci_dev *dev;
unsigned char orig, config;
- sio_pci_route();
common_init_pci();
+ sio_pci_route();
/*
* On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
@@ -325,7 +325,7 @@ struct alpha_machine_vector alphabook1_mv __initmv = {
init_irq: sio_init_irq,
init_pit: common_init_pit,
init_pci: alphabook1_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
@@ -359,7 +359,6 @@ struct alpha_machine_vector avanti_mv __initmv = {
init_irq: sio_init_irq,
init_pit: common_init_pit,
init_pci: noname_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
@@ -392,7 +391,6 @@ struct alpha_machine_vector noname_mv __initmv = {
init_irq: sio_init_irq,
init_pit: common_init_pit,
init_pci: noname_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
@@ -434,7 +432,6 @@ struct alpha_machine_vector p2k_mv __initmv = {
init_irq: sio_init_irq,
init_pit: common_init_pit,
init_pci: noname_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: p2k_map_irq,
pci_swizzle: common_swizzle,
@@ -467,7 +464,6 @@ struct alpha_machine_vector xl_mv __initmv = {
init_irq: sio_init_irq,
init_pit: common_init_pit,
init_pci: noname_init_pci,
- kill_arch: common_kill_arch,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
index a8c7698fb..6ad08e442 100644
--- a/arch/alpha/kernel/sys_sx164.c
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -26,7 +26,7 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -211,7 +211,7 @@ struct alpha_machine_vector sx164_mv __initmv = {
init_irq: sx164_init_irq,
init_pit: common_init_pit,
init_pci: sx164_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: sx164_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index c592ee65e..a17cd4de6 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -25,7 +25,7 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -40,9 +40,13 @@ takara_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
outb(mask, 0x21); /* ISA PIC1 */
else
outb(mask >> 8, 0xA1); /* ISA PIC2 */
- } else if (irq <= 31) {
- regaddr = 0x510 + ((irq - 16) & 0x0c);
- outl((mask >> ((irq - 16) & 0x0c)) & 0xf0000Ul, regaddr);
+ } else {
+ if (irq > 63)
+ mask = _alpha_irq_masks[1] << 16;
+ else
+ mask = mask >> ((irq - 16) & 0x30);
+ regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
+ outl(mask & 0xffff0000UL, regaddr);
}
}
@@ -87,10 +91,6 @@ static void
takara_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
int irq = (vector - 0x800) >> 4;
-
- if (irq > 15)
- irq = ((vector - 0x800) >> 6) + 12;
-
handle_irq(irq, irq, regs);
}
@@ -99,10 +99,9 @@ takara_init_irq(void)
{
STANDARD_INIT_IRQ_PROLOG;
- if (alpha_using_srm)
+ if (alpha_using_srm) {
alpha_mv.device_interrupt = takara_srm_device_interrupt;
-
- if (!alpha_using_srm) {
+ } else {
unsigned int ctlreg = inl(0x500);
/* Return to non-accelerated mode. */
@@ -127,6 +126,37 @@ takara_init_irq(void)
*/
static int __init
+takara_map_irq_srm(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ static char irq_tab[15][5] __initlocaldata = {
+ { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
+ { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
+ { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
+ /* These are behind the bridges. */
+ { 12, 12, 13, 14, 15}, /* slot 12 == nothing */
+ { 8, 8, 9, 19, 11}, /* slot 13 == nothing */
+ { 4, 4, 5, 6, 7}, /* slot 14 == nothing */
+ { 0, 0, 1, 2, 3}, /* slot 15 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
+ {64+ 0, 64+0, 64+1, 64+2, 64+3}, /* slot 17= device 4 */
+ {48+ 0, 48+0, 48+1, 48+2, 48+3}, /* slot 18= device 3 */
+ {32+ 0, 32+0, 32+1, 32+2, 32+3}, /* slot 19= device 2 */
+ {16+ 0, 16+0, 16+1, 16+2, 16+3}, /* slot 20= device 1 */
+ };
+ const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP;
+ if (irq >= 0 && irq < 16) {
+ /* Guess that we are behind a bridge. */
+ unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
+ irq += irq_tab[busslot-min_idsel][0];
+ }
+ return irq;
+}
+
+static int __init
takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[15][5] __initlocaldata = {
@@ -165,10 +195,13 @@ takara_swizzle(struct pci_dev *dev, u8 *pinp)
if (pin == 1)
pin += (20 - busslot);
else {
- /* Must be a card-based bridge. */
- printk(KERN_WARNING "takara_swizzle: cannot handle "
- "card-bridge behind builtin bridge yet.\n");
+ printk(KERN_WARNING "takara_swizzle: can only "
+ "handle cards with INTA IRQ pin.\n");
}
+ } else {
+ /* Must be a card-based bridge. */
+ printk(KERN_WARNING "takara_swizzle: cannot handle "
+ "card-bridge behind builtin bridge yet.\n");
}
*pinp = pin;
@@ -178,8 +211,11 @@ takara_swizzle(struct pci_dev *dev, u8 *pinp)
static void __init
takara_init_pci(void)
{
+ if (alpha_using_srm)
+ alpha_mv.pci_map_irq = takara_map_irq_srm;
+
common_init_pci();
- /* ns87312_enable_ide(0x26e); */
+ ns87312_enable_ide(0x26e);
}
@@ -198,8 +234,8 @@ struct alpha_machine_vector takara_mv __initmv = {
min_io_address: DEFAULT_IO_BASE,
min_mem_address: CIA_DEFAULT_MEM_BASE,
- nr_irqs: 20,
- irq_probe_mask: _PROBE_MASK(20),
+ nr_irqs: 128,
+ irq_probe_mask: _PROBE_MASK(48),
update_irq_hw: takara_update_irq_hw,
ack_irq: common_ack_irq,
device_interrupt: takara_device_interrupt,
@@ -208,7 +244,7 @@ struct alpha_machine_vector takara_mv __initmv = {
init_irq: takara_init_irq,
init_pit: common_init_pit,
init_pci: takara_init_pci,
- kill_arch: common_kill_arch,
+ kill_arch: NULL,
pci_map_irq: takara_map_irq,
pci_swizzle: takara_swizzle,
};
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index a86c79cc1..6e528e08f 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -40,7 +40,7 @@
#include <linux/timex.h>
#include "proto.h"
-#include "irq_impl.h"
+#include <asm/hw_irq.h>
extern rwlock_t xtime_lock;
extern volatile unsigned long lost_ticks; /* kernel/sched.c */
@@ -174,7 +174,7 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
#ifdef CONFIG_RTC
void
-rtc_init_pit (void)
+rtc_init_pit(void)
{
unsigned char control;
@@ -193,6 +193,25 @@ rtc_init_pit (void)
outb(0x31, 0x42);
outb(0x13, 0x42);
}
+
+void
+rtc_kill_pit(void)
+{
+ unsigned char control;
+
+ cli();
+
+ /* Reset periodic interrupt frequency. */
+ CMOS_WRITE(0x26, RTC_FREQ_SELECT);
+
+ /* Turn on periodic interrupts. */
+ control = CMOS_READ(RTC_CONTROL);
+ control |= RTC_PIE;
+ CMOS_WRITE(control, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+
+ sti();
+}
#endif
void
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 59f021a77..36b0cc43a 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -113,7 +113,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
}
#ifndef CONFIG_MATHEMU
-static long dummy_emul() { return 0; }
+static long dummy_emul(void) { return 0; }
long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
= (void *)dummy_emul;
long (*alpha_fp_emul) (unsigned long pc)
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index f550ba7cb..a224f84bb 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -7,7 +7,7 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
strchr.o strrchr.o memchr.o \
copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
- csum_ipv6_magic.o strcasecmp.o semaphore.o \
+ csum_ipv6_magic.o strcasecmp.o semaphore.o fpreg.o \
srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
lib.a: $(OBJS)
diff --git a/arch/alpha/kernel/fpreg.c b/arch/alpha/lib/fpreg.c
index 0bd8b9f67..c09d257bc 100644
--- a/arch/alpha/kernel/fpreg.c
+++ b/arch/alpha/lib/fpreg.c
@@ -1,5 +1,5 @@
/*
- * arch/alpha/kernel/fpreg.c
+ * arch/alpha/lib/fpreg.c
*
* (C) Copyright 1998 Linus Torvalds
*/
@@ -96,3 +96,96 @@ alpha_write_fp_reg (unsigned long reg, unsigned long val)
case 31: LDT(31, val); break;
}
}
+
+#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#define STS(reg,val) asm volatile ("ftois $f"#reg",%0" : "=r"(val));
+#else
+#define STS(reg,val) asm volatile ("sts $f"#reg",%0" : "=m"(val));
+#endif
+
+unsigned long
+alpha_read_fp_reg_s (unsigned long reg)
+{
+ unsigned long val;
+
+ switch (reg) {
+ case 0: STS( 0, val); break;
+ case 1: STS( 1, val); break;
+ case 2: STS( 2, val); break;
+ case 3: STS( 3, val); break;
+ case 4: STS( 4, val); break;
+ case 5: STS( 5, val); break;
+ case 6: STS( 6, val); break;
+ case 7: STS( 7, val); break;
+ case 8: STS( 8, val); break;
+ case 9: STS( 9, val); break;
+ case 10: STS(10, val); break;
+ case 11: STS(11, val); break;
+ case 12: STS(12, val); break;
+ case 13: STS(13, val); break;
+ case 14: STS(14, val); break;
+ case 15: STS(15, val); break;
+ case 16: STS(16, val); break;
+ case 17: STS(17, val); break;
+ case 18: STS(18, val); break;
+ case 19: STS(19, val); break;
+ case 20: STS(20, val); break;
+ case 21: STS(21, val); break;
+ case 22: STS(22, val); break;
+ case 23: STS(23, val); break;
+ case 24: STS(24, val); break;
+ case 25: STS(25, val); break;
+ case 26: STS(26, val); break;
+ case 27: STS(27, val); break;
+ case 28: STS(28, val); break;
+ case 29: STS(29, val); break;
+ case 30: STS(30, val); break;
+ case 31: STS(31, val); break;
+ }
+ return val;
+}
+
+#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#define LDS(reg,val) asm volatile ("itofs %0,$f"#reg : : "r"(val));
+#else
+#define LDS(reg,val) asm volatile ("lds $f"#reg",%0" : : "m"(val));
+#endif
+
+void
+alpha_write_fp_reg_s (unsigned long reg, unsigned long val)
+{
+ switch (reg) {
+ case 0: LDS( 0, val); break;
+ case 1: LDS( 1, val); break;
+ case 2: LDS( 2, val); break;
+ case 3: LDS( 3, val); break;
+ case 4: LDS( 4, val); break;
+ case 5: LDS( 5, val); break;
+ case 6: LDS( 6, val); break;
+ case 7: LDS( 7, val); break;
+ case 8: LDS( 8, val); break;
+ case 9: LDS( 9, val); break;
+ case 10: LDS(10, val); break;
+ case 11: LDS(11, val); break;
+ case 12: LDS(12, val); break;
+ case 13: LDS(13, val); break;
+ case 14: LDS(14, val); break;
+ case 15: LDS(15, val); break;
+ case 16: LDS(16, val); break;
+ case 17: LDS(17, val); break;
+ case 18: LDS(18, val); break;
+ case 19: LDS(19, val); break;
+ case 20: LDS(20, val); break;
+ case 21: LDS(21, val); break;
+ case 22: LDS(22, val); break;
+ case 23: LDS(23, val); break;
+ case 24: LDS(24, val); break;
+ case 25: LDS(25, val); break;
+ case 26: LDS(26, val); break;
+ case 27: LDS(27, val); break;
+ case 28: LDS(28, val); break;
+ case 29: LDS(29, val); break;
+ case 30: LDS(30, val); break;
+ case 31: LDS(31, val); break;
+ }
+}
diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c
index 25de0f871..de592ff08 100644
--- a/arch/alpha/lib/io.c
+++ b/arch/alpha/lib/io.c
@@ -2,8 +2,11 @@
* Alpha IO and memory functions.. Just expand the inlines in the header
* files..
*/
+
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/string.h>
+
#include <asm/io.h>
unsigned int _inb(unsigned long addr)
@@ -562,3 +565,28 @@ void _memset_c_io(unsigned long to, unsigned long c, long count)
}
mb();
}
+
+void
+scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
+{
+ if (! __is_ioaddr((unsigned long) s)) {
+ /* Source is memory. */
+ if (! __is_ioaddr((unsigned long) d))
+ memcpy(d, s, count);
+ else
+ memcpy_toio(d, s, count);
+ } else {
+ /* Source is screen. */
+ if (! __is_ioaddr((unsigned long) d))
+ memcpy_fromio(d, s, count);
+ else {
+ /* FIXME: Should handle unaligned ops and
+ operation widening. */
+ count /= 2;
+ while (count--) {
+ u16 tmp = __raw_readw((unsigned long)(s++));
+ __raw_writew(tmp, (unsigned long)(d++));
+ }
+ }
+ }
+}
diff --git a/arch/alpha/math-emu/Makefile b/arch/alpha/math-emu/Makefile
index 6ea85465f..b5fc37765 100644
--- a/arch/alpha/math-emu/Makefile
+++ b/arch/alpha/math-emu/Makefile
@@ -1,9 +1,15 @@
#
-# Makefile for math-emulator files...
+# Makefile for the FPU instruction emulation.
#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := math-emu.o
-O_OBJS := fp-emul.o ieee-math.o
+O_OBJS := math.o
+CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w
ifeq ($(CONFIG_MATHEMU),m)
M_OBJS := $(O_TARGET)
diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c
deleted file mode 100644
index c2ebbbb60..000000000
--- a/arch/alpha/math-emu/fp-emul.c
+++ /dev/null
@@ -1,354 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/uaccess.h>
-
-#include "ieee-math.h"
-
-#define OPC_PAL 0x00
-
-#define OPC_INTA 0x10
-#define OPC_INTL 0x11
-#define OPC_INTS 0x12
-#define OPC_INTM 0x13
-#define OPC_FLTC 0x14
-#define OPC_FLTV 0x15
-#define OPC_FLTI 0x16
-#define OPC_FLTL 0x17
-
-#define OPC_MISC 0x18
-
-#define OPC_JSR 0x1a
-
-#define OP_FUN(OP,FUN) ((OP << 26) | (FUN << 5))
-
-/*
- * "Base" function codes for the FLTI-class instructions.
- * Note that in most cases these actually correspond to the "chopped"
- * form of the instruction. Not to worry---we extract the qualifier
- * bits separately and deal with them separately. Notice that base
- * function code 0x2c is used for both CVTTS and CVTST. The other bits
- * in the function code are used to distinguish the two.
- */
-#define FLTI_FUNC_ADDS OP_FUN(OPC_FLTI, 0x000)
-#define FLTI_FUNC_ADDT OP_FUN(OPC_FLTI, 0x020)
-#define FLTI_FUNC_CMPTEQ OP_FUN(OPC_FLTI, 0x025)
-#define FLTI_FUNC_CMPTLT OP_FUN(OPC_FLTI, 0x026)
-#define FLTI_FUNC_CMPTLE OP_FUN(OPC_FLTI, 0x027)
-#define FLTI_FUNC_CMPTUN OP_FUN(OPC_FLTI, 0x024)
-#define FLTI_FUNC_CVTTS_or_CVTST OP_FUN(OPC_FLTI, 0x02c)
-#define FLTI_FUNC_CVTTQ OP_FUN(OPC_FLTI, 0x02f)
-#define FLTI_FUNC_CVTQS OP_FUN(OPC_FLTI, 0x03c)
-#define FLTI_FUNC_CVTQT OP_FUN(OPC_FLTI, 0x03e)
-#define FLTI_FUNC_DIVS OP_FUN(OPC_FLTI, 0x003)
-#define FLTI_FUNC_DIVT OP_FUN(OPC_FLTI, 0x023)
-#define FLTI_FUNC_MULS OP_FUN(OPC_FLTI, 0x002)
-#define FLTI_FUNC_MULT OP_FUN(OPC_FLTI, 0x022)
-#define FLTI_FUNC_SUBS OP_FUN(OPC_FLTI, 0x001)
-#define FLTI_FUNC_SUBT OP_FUN(OPC_FLTI, 0x021)
-
-#define FLTC_FUNC_SQRTS OP_FUN(OPC_FLTC, 0x00B)
-#define FLTC_FUNC_SQRTT OP_FUN(OPC_FLTC, 0x02B)
-
-#define FLTL_FUNC_CVTQL OP_FUN(OPC_FLTL, 0x030)
-
-#define MISC_TRAPB 0x0000
-#define MISC_EXCB 0x0400
-
-extern unsigned long alpha_read_fp_reg (unsigned long reg);
-extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
-
-
-#ifdef MODULE
-
-MODULE_DESCRIPTION("FP Software completion module");
-
-extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
-extern long (*alpha_fp_emul) (unsigned long pc);
-
-static long (*save_emul_imprecise)(struct pt_regs *, unsigned long);
-static long (*save_emul) (unsigned long pc);
-
-long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
-long do_alpha_fp_emul(unsigned long);
-
-int init_module(void)
-{
- save_emul_imprecise = alpha_fp_emul_imprecise;
- save_emul = alpha_fp_emul;
- alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise;
- alpha_fp_emul = do_alpha_fp_emul;
- return 0;
-}
-
-void cleanup_module(void)
-{
- alpha_fp_emul_imprecise = save_emul_imprecise;
- alpha_fp_emul = save_emul;
-}
-
-#undef alpha_fp_emul_imprecise
-#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
-#undef alpha_fp_emul
-#define alpha_fp_emul do_alpha_fp_emul
-
-#endif /* MODULE */
-
-/*
- * Emulate the floating point instruction at address PC. Returns 0 if
- * emulation fails. Notice that the kernel does not and cannot use FP
- * regs. This is good because it means that instead of
- * saving/restoring all fp regs, we simply stick the result of the
- * operation into the appropriate register.
- */
-long
-alpha_fp_emul (unsigned long pc)
-{
- unsigned long op_fun, fa, fb, fc, func, mode;
- unsigned long fpcw = current->thread.flags;
- unsigned long va, vb, vc, res, fpcr;
- __u32 insn;
-
- MOD_INC_USE_COUNT;
-
- get_user(insn, (__u32*)pc);
- fc = (insn >> 0) & 0x1f; /* destination register */
- fb = (insn >> 16) & 0x1f;
- fa = (insn >> 21) & 0x1f;
- func = (insn >> 5) & 0x7ff;
- mode = (insn >> 5) & 0xc0;
- op_fun = insn & OP_FUN(0x3f, 0x3f);
-
- va = alpha_read_fp_reg(fa);
- vb = alpha_read_fp_reg(fb);
- fpcr = rdfpcr();
-
- /*
- * Try the operation in software. First, obtain the rounding
- * mode...
- */
- if (mode == 0xc0) {
- /* dynamic---get rounding mode from fpcr: */
- mode = ((fpcr & FPCR_DYN_MASK) >> FPCR_DYN_SHIFT) << ROUND_SHIFT;
- }
- mode |= (fpcw & IEEE_TRAP_ENABLE_MASK);
-
- if ((IEEE_TRAP_ENABLE_MASK & 0xc0)) {
- extern int something_is_wrong (void);
- something_is_wrong();
- }
-
- switch (op_fun) {
- case FLTI_FUNC_CMPTEQ:
- res = ieee_CMPTEQ(va, vb, &vc);
- break;
-
- case FLTI_FUNC_CMPTLT:
- res = ieee_CMPTLT(va, vb, &vc);
- break;
-
- case FLTI_FUNC_CMPTLE:
- res = ieee_CMPTLE(va, vb, &vc);
- break;
-
- case FLTI_FUNC_CMPTUN:
- res = ieee_CMPTUN(va, vb, &vc);
- break;
-
- case FLTL_FUNC_CVTQL:
- /*
- * Notice: We can get here only due to an integer
- * overflow. Such overflows are reported as invalid
- * ops. We return the result the hw would have
- * computed.
- */
- vc = ((vb & 0xc0000000) << 32 | /* sign and msb */
- (vb & 0x3fffffff) << 29); /* rest of the integer */
- res = FPCR_INV;
- break;
-
- case FLTI_FUNC_CVTQS:
- res = ieee_CVTQS(mode, vb, &vc);
- break;
-
- case FLTI_FUNC_CVTQT:
- res = ieee_CVTQT(mode, vb, &vc);
- break;
-
- case FLTI_FUNC_CVTTS_or_CVTST:
- if (func == 0x6ac) {
- /*
- * 0x2ac is also CVTST, but if the /S
- * qualifier isn't set, we wouldn't be here in
- * the first place...
- */
- res = ieee_CVTST(mode, vb, &vc);
- } else {
- res = ieee_CVTTS(mode, vb, &vc);
- }
- break;
-
- case FLTI_FUNC_DIVS:
- res = ieee_DIVS(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_DIVT:
- res = ieee_DIVT(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_MULS:
- res = ieee_MULS(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_MULT:
- res = ieee_MULT(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_SUBS:
- res = ieee_SUBS(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_SUBT:
- res = ieee_SUBT(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_ADDS:
- res = ieee_ADDS(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_ADDT:
- res = ieee_ADDT(mode, va, vb, &vc);
- break;
-
- case FLTI_FUNC_CVTTQ:
- res = ieee_CVTTQ(mode, vb, &vc);
- break;
-
- case FLTC_FUNC_SQRTS:
- res = ieee_SQRTS(mode, vb, &vc);
- break;
-
- case FLTC_FUNC_SQRTT:
- res = ieee_SQRTT(mode, vb, &vc);
- break;
-
- default:
- printk("alpha_fp_emul: unexpected function code %#lx at %#lx\n",
- func & 0x3f, pc);
- MOD_DEC_USE_COUNT;
- return 0;
- }
-
- /*
- * Take the appropriate action for each possible
- * floating-point result:
- *
- * - Set the appropriate bits in the FPCR
- * - If the specified exception is enabled in the FPCR,
- * return. The caller (entArith) will dispatch
- * the appropriate signal to the translated program.
- *
- * In addition, properly track the exception state in software
- * as described in the Alpha Architectre Handbook section 4.7.7.3.
- */
- if (res) {
- /* Record exceptions in software control word. */
- current->thread.flags = fpcw |= res >> 35;
-
- /* Update hardware control register */
- fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
- fpcr |= ieee_swcr_to_fpcr(fpcw);
- wrfpcr(fpcr);
-
- /* Do we generate a signal? */
- if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) {
- MOD_DEC_USE_COUNT;
- return 0;
- }
- }
-
- /*
- * Whoo-kay... we got this far, and we're not generating a signal
- * to the translated program. All that remains is to write the
- * result:
- */
- alpha_write_fp_reg(fc, vc);
-
- MOD_DEC_USE_COUNT;
- return 1;
-}
-
-
-long
-alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
-{
- unsigned long trigger_pc = regs->pc - 4;
- unsigned long insn, opcode, rc;
-
- MOD_INC_USE_COUNT;
-
- /*
- * Turn off the bits corresponding to registers that are the
- * target of instructions that set bits in the exception
- * summary register. We have some slack doing this because a
- * register that is the target of a trapping instruction can
- * be written at most once in the trap shadow.
- *
- * Branches, jumps, TRAPBs, EXCBs and calls to PALcode all
- * bound the trap shadow, so we need not look any further than
- * up to the first occurrence of such an instruction.
- */
- while (write_mask) {
- get_user(insn, (__u32*)(trigger_pc));
- opcode = insn >> 26;
- rc = insn & 0x1f;
-
- switch (opcode) {
- case OPC_PAL:
- case OPC_JSR:
- case 0x30 ... 0x3f: /* branches */
- MOD_DEC_USE_COUNT;
- return 0;
-
- case OPC_MISC:
- switch (insn & 0xffff) {
- case MISC_TRAPB:
- case MISC_EXCB:
- MOD_DEC_USE_COUNT;
- return 0;
-
- default:
- break;
- }
- break;
-
- case OPC_INTA:
- case OPC_INTL:
- case OPC_INTS:
- case OPC_INTM:
- write_mask &= ~(1UL << rc);
- break;
-
- case OPC_FLTC:
- case OPC_FLTV:
- case OPC_FLTI:
- case OPC_FLTL:
- write_mask &= ~(1UL << (rc + 32));
- break;
- }
- if (!write_mask) {
- if (alpha_fp_emul(trigger_pc)) {
- /* re-execute insns in trap-shadow: */
- regs->pc = trigger_pc + 4;
- MOD_DEC_USE_COUNT;
- return 1;
- }
- break;
- }
- trigger_pc -= 4;
- }
- MOD_DEC_USE_COUNT;
- return 0;
-}
diff --git a/arch/alpha/math-emu/fp-emul.h b/arch/alpha/math-emu/fp-emul.h
deleted file mode 100644
index 12965fedc..000000000
--- a/arch/alpha/math-emu/fp-emul.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * These defines correspond to the dynamic rounding mode bits in the
- * Floating Point Control Register. They also happen to correspond to
- * the instruction encodings except that 0x03 signifies dynamic
- * rounding mode in that case.
- */
-#define ROUND_CHOP 0x00 /* chopped (aka round towards zero) */
-#define ROUND_NINF 0x01 /* round towards negative infinity */
-#define ROUND_NEAR 0x02 /* round towards nearest number */
-#define ROUND_PINF 0x03 /* round towards positive infinity */
diff --git a/arch/alpha/math-emu/ieee-math.c b/arch/alpha/math-emu/ieee-math.c
deleted file mode 100644
index 9a86b1048..000000000
--- a/arch/alpha/math-emu/ieee-math.c
+++ /dev/null
@@ -1,1382 +0,0 @@
-/*
- * ieee-math.c - IEEE floating point emulation code
- * Copyright (C) 1989,1990,1991,1995 by
- * Digital Equipment Corporation, Maynard, Massachusetts.
- *
- * Heavily modified for Linux/Alpha. Changes are Copyright (c) 1995
- * by David Mosberger (davidm@azstarnet.com).
- *
- * This file may be redistributed according to the terms of the
- * GNU General Public License.
- */
-/*
- * The original code did not have any comments. I have created many
- * comments as I fix the bugs in the code. My comments are based on
- * my observation and interpretation of the code. If the original
- * author would have spend a few minutes to comment the code, we would
- * never had a problem of misinterpretation. -HA
- *
- * This code could probably be a lot more optimized (especially the
- * division routine). However, my foremost concern was to get the
- * IEEE behavior right. Performance is less critical as these
- * functions are used on exceptional numbers only (well, assuming you
- * don't turn on the "trap on inexact"...).
- */
-#include <linux/sched.h>
-#include "ieee-math.h"
-
-#define STICKY_S 0x20000000 /* both in longword 0 of fraction */
-#define STICKY_T 1
-
-/*
- * Careful: order matters here!
- */
-enum {
- NaN, QNaN, INFTY, ZERO, DENORM, NORMAL
-};
-
-enum {
- SINGLE, DOUBLE
-};
-
-typedef unsigned long fpclass_t;
-
-#define IEEE_TMAX 0x7fefffffffffffff
-#define IEEE_SMAX 0x47efffffe0000000
-#define IEEE_SNaN 0xfff00000000f0000
-#define IEEE_QNaN 0xfff8000000000000
-#define IEEE_PINF 0x7ff0000000000000
-#define IEEE_NINF 0xfff0000000000000
-
-
-/*
- * The memory format of S floating point numbers differs from the
- * register format. In the following, the bitnumbers above the
- * diagram below give the memory format while the numbers below give
- * the register format.
- *
- * 31 30 23 22 0
- * +-----------------------------------------------+
- * S | s | exp | fraction |
- * +-----------------------------------------------+
- * 63 62 52 51 29
- *
- * For T floating point numbers, the register and memory formats
- * match:
- *
- * +-------------------------------------------------------------------+
- * T | s | exp | frac | tion |
- * +-------------------------------------------------------------------+
- * 63 62 52 51 32 31 0
- */
-typedef struct {
- unsigned long f[2]; /* bit 55 in f[0] is the factor of 2^0*/
- int s; /* 1 bit sign (0 for +, 1 for -) */
- int e; /* 16 bit signed exponent */
-} EXTENDED;
-
-
-/*
- * Return the sign of a Q integer, S or T fp number in the register
- * format.
- */
-static inline int
-sign (unsigned long a)
-{
- if ((long) a < 0)
- return -1;
- else
- return 1;
-}
-
-
-static inline long
-cmp128 (const long a[2], const long b[2])
-{
- if (a[1] < b[1]) return -1;
- if (a[1] > b[1]) return 1;
- return a[0] - b[0];
-}
-
-
-static inline void
-sll128 (unsigned long a[2])
-{
- a[1] = (a[1] << 1) | (a[0] >> 63);
- a[0] <<= 1;
-}
-
-
-static inline void
-srl128 (unsigned long a[2])
-{
- a[0] = (a[0] >> 1) | (a[1] << 63);
- a[1] >>= 1;
-}
-
-
-static inline void
-add128 (const unsigned long a[2], const unsigned long b[2], unsigned long c[2])
-{
- unsigned long carry = a[0] > (0xffffffffffffffff - b[0]);
-
- c[0] = a[0] + b[0];
- c[1] = a[1] + b[1] + carry;
-}
-
-
-static inline void
-sub128 (const unsigned long a[2], const unsigned long b[2], unsigned long c[2])
-{
- unsigned long borrow = a[0] < b[0];
-
- c[0] = a[0] - b[0];
- c[1] = a[1] - b[1] - borrow;
-}
-
-
-static inline void
-mul64 (const unsigned long a, const unsigned long b, unsigned long c[2])
-{
- c[0] = a * b;
- asm ("umulh %1,%2,%0" : "=r"(c[1]) : "r"(a), "r"(b));
-}
-
-
-static void
-div128 (unsigned long a[2], unsigned long b[2], unsigned long c[2])
-{
- unsigned long mask[2] = {1, 0};
-
- /*
- * Shift b until either the sign bit is set or until it is at
- * least as big as the dividend:
- */
- while (cmp128(b, a) < 0 && sign(b[1]) >= 0) {
- sll128(b);
- sll128(mask);
- }
- c[0] = c[1] = 0;
- do {
- if (cmp128(a, b) >= 0) {
- sub128(a, b, a);
- add128(mask, c, c);
- }
- srl128(mask);
- srl128(b);
- } while (mask[0] || mask[1]);
-}
-
-
-static void
-normalize (EXTENDED *a)
-{
- if (!a->f[0] && !a->f[1])
- return; /* zero fraction, unnormalizable... */
- /*
- * In "extended" format, the "1" in "1.f" is explicit; it is
- * in bit 55 of f[0], and the decimal point is understood to
- * be between bit 55 and bit 54. To normalize, shift the
- * fraction until we have a "1" in bit 55.
- */
- if ((a->f[0] & 0xff00000000000000) != 0 || a->f[1] != 0) {
- /*
- * Mantissa is greater than 1.0:
- */
- while ((a->f[0] & 0xff80000000000000) != 0x0080000000000000 ||
- a->f[1] != 0)
- {
- unsigned long sticky;
-
- ++a->e;
- sticky = a->f[0] & 1;
- srl128(a->f);
- a->f[0] |= sticky;
- }
- return;
- }
-
- if (!(a->f[0] & 0x0080000000000000)) {
- /*
- * Mantissa is less than 1.0:
- */
- while (!(a->f[0] & 0x0080000000000000)) {
- --a->e;
- a->f[0] <<= 1;
- }
- return;
- }
-}
-
-
-static inline fpclass_t
-ieee_fpclass (unsigned long a)
-{
- unsigned long exp, fract;
-
- exp = (a >> 52) & 0x7ff; /* 11 bits of exponent */
- fract = a & 0x000fffffffffffff; /* 52 bits of fraction */
- if (exp == 0) {
- if (fract == 0)
- return ZERO;
- return DENORM;
- }
- if (exp == 0x7ff) {
- if (fract == 0)
- return INFTY;
- if (((fract >> 51) & 1) != 0)
- return QNaN;
- return NaN;
- }
- return NORMAL;
-}
-
-
-/*
- * Translate S/T fp number in register format into extended format.
- */
-static fpclass_t
-extend_ieee (unsigned long a, EXTENDED *b, int prec)
-{
- fpclass_t result_kind;
-
- b->s = a >> 63;
- b->e = ((a >> 52) & 0x7ff) - 0x3ff; /* remove bias */
- b->f[1] = 0;
- /*
- * We shift f[1] left three bits so that the higher order bits
- * of the fraction will reside in bits 55 through 0 of f[0].
- */
- b->f[0] = (a & 0x000fffffffffffff) << 3;
- result_kind = ieee_fpclass(a);
- if (result_kind == NORMAL) {
- /* set implied 1. bit: */
- b->f[0] |= 1UL << 55;
- } else if (result_kind == DENORM) {
- if (prec == SINGLE)
- b->e = -126;
- else
- b->e = -1022;
- }
- return result_kind;
-}
-
-
-/*
- * INPUT PARAMETERS:
- * a a number in EXTENDED format to be converted to
- * s-floating format.
- * f rounding mode and exception enable bits.
- * OUTPUT PARAMETERS:
- * b will contain the s-floating number that "a" was
- * converted to (in register format).
- */
-static unsigned long
-make_s_ieee (long f, EXTENDED *a, unsigned long *b)
-{
- unsigned long res, sticky;
-
- if (!a->e && !a->f[0] && !a->f[1]) {
- *b = (unsigned long) a->s << 63; /* return +/-0 */
- return 0;
- }
-
- normalize(a);
- res = 0;
-
- if (a->e < -0x7e) {
- res = FPCR_INE;
- if (f & IEEE_TRAP_ENABLE_UNF) {
- res |= FPCR_UNF;
- a->e += 0xc0; /* scale up result by 2^alpha */
- } else {
- /* try making denormalized number: */
- while (a->e < -0x7e) {
- ++a->e;
- sticky = a->f[0] & 1;
- srl128(a->f);
- if (!a->f[0] && !a->f[0]) {
- /* underflow: replace with exact 0 */
- res |= FPCR_UNF;
- break;
- }
- a->f[0] |= sticky;
- }
- a->e = -0x3ff;
- }
- }
- if (a->e >= 0x80) {
- res = FPCR_OVF | FPCR_INE;
- if (f & IEEE_TRAP_ENABLE_OVF) {
- a->e -= 0xc0; /* scale down result by 2^alpha */
- } else {
- /*
- * Overflow without trap enabled, substitute
- * result according to rounding mode:
- */
- switch (RM(f)) {
- case ROUND_NEAR:
- *b = IEEE_PINF;
- break;
-
- case ROUND_CHOP:
- *b = IEEE_SMAX;
- break;
-
- case ROUND_NINF:
- if (a->s) {
- *b = IEEE_PINF;
- } else {
- *b = IEEE_SMAX;
- }
- break;
-
- case ROUND_PINF:
- if (a->s) {
- *b = IEEE_SMAX;
- } else {
- *b = IEEE_PINF;
- }
- break;
- }
- *b |= ((unsigned long) a->s << 63);
- return res;
- }
- }
-
- *b = (((unsigned long) a->s << 63) |
- (((unsigned long) a->e + 0x3ff) << 52) |
- ((a->f[0] >> 3) & 0x000fffffe0000000));
- return res;
-}
-
-
-static unsigned long
-make_t_ieee (long f, EXTENDED *a, unsigned long *b)
-{
- unsigned long res, sticky;
-
- if (!a->e && !a->f[0] && !a->f[1]) {
- *b = (unsigned long) a->s << 63; /* return +/-0 */
- return 0;
- }
-
- normalize(a);
- res = 0;
- if (a->e < -0x3fe) {
- res = FPCR_INE;
- if (f & IEEE_TRAP_ENABLE_UNF) {
- res |= FPCR_UNF;
- a->e += 0x600;
- } else {
- /* try making denormalized number: */
- while (a->e < -0x3fe) {
- ++a->e;
- sticky = a->f[0] & 1;
- srl128(a->f);
- if (!a->f[0] && !a->f[0]) {
- /* underflow: replace with exact 0 */
- res |= FPCR_UNF;
- break;
- }
- a->f[0] |= sticky;
- }
- a->e = -0x3ff;
- }
- }
- if (a->e >= 0x3ff) {
- res = FPCR_OVF | FPCR_INE;
- if (f & IEEE_TRAP_ENABLE_OVF) {
- a->e -= 0x600; /* scale down result by 2^alpha */
- } else {
- /*
- * Overflow without trap enabled, substitute
- * result according to rounding mode:
- */
- switch (RM(f)) {
- case ROUND_NEAR:
- *b = IEEE_PINF;
- break;
-
- case ROUND_CHOP:
- *b = IEEE_TMAX;
- break;
-
- case ROUND_NINF:
- if (a->s) {
- *b = IEEE_PINF;
- } else {
- *b = IEEE_TMAX;
- }
- break;
-
- case ROUND_PINF:
- if (a->s) {
- *b = IEEE_TMAX;
- } else {
- *b = IEEE_PINF;
- }
- break;
- }
- *b |= ((unsigned long) a->s << 63);
- return res;
- }
- }
- *b = (((unsigned long) a->s << 63) |
- (((unsigned long) a->e + 0x3ff) << 52) |
- ((a->f[0] >> 3) & 0x000fffffffffffff));
- return res;
-}
-
-
-/*
- * INPUT PARAMETERS:
- * a EXTENDED format number to be rounded.
- * rm integer with value ROUND_NEAR, ROUND_CHOP, etc.
- * indicates how "a" should be rounded to produce "b".
- * OUTPUT PARAMETERS:
- * b s-floating number produced by rounding "a".
- * RETURN VALUE:
- * if no errors occurred, will be zero. Else will contain flags
- * like FPCR_INE_OP, etc.
- */
-static unsigned long
-round_s_ieee (int f, EXTENDED *a, unsigned long *b)
-{
- unsigned long diff1, diff2, res = 0;
- EXTENDED z1, z2;
-
- if (!(a->f[0] & 0xffffffff)) {
- return make_s_ieee(f, a, b); /* no rounding error */
- }
-
- /*
- * z1 and z2 are the S-floating numbers with the next smaller/greater
- * magnitude than a, respectively.
- */
- z1.s = z2.s = a->s;
- z1.e = z2.e = a->e;
- z1.f[0] = z2.f[0] = a->f[0] & 0xffffffff00000000;
- z1.f[1] = z2.f[1] = 0;
- z2.f[0] += 0x100000000; /* next bigger S float number */
-
- switch (RM(f)) {
- case ROUND_NEAR:
- diff1 = a->f[0] - z1.f[0];
- diff2 = z2.f[0] - a->f[0];
- if (diff1 > diff2)
- res = make_s_ieee(f, &z2, b);
- else if (diff2 > diff1)
- res = make_s_ieee(f, &z1, b);
- else
- /* equal distance: round towards even */
- if (z1.f[0] & 0x100000000)
- res = make_s_ieee(f, &z2, b);
- else
- res = make_s_ieee(f, &z1, b);
- break;
-
- case ROUND_CHOP:
- res = make_s_ieee(f, &z1, b);
- break;
-
- case ROUND_PINF:
- if (a->s) {
- res = make_s_ieee(f, &z1, b);
- } else {
- res = make_s_ieee(f, &z2, b);
- }
- break;
-
- case ROUND_NINF:
- if (a->s) {
- res = make_s_ieee(f, &z2, b);
- } else {
- res = make_s_ieee(f, &z1, b);
- }
- break;
- }
- return FPCR_INE | res;
-}
-
-
-static unsigned long
-round_t_ieee (int f, EXTENDED *a, unsigned long *b)
-{
- unsigned long diff1, diff2, res;
- EXTENDED z1, z2;
-
- if (!(a->f[0] & 0x7)) {
- /* no rounding error */
- return make_t_ieee(f, a, b);
- }
-
- z1.s = z2.s = a->s;
- z1.e = z2.e = a->e;
- z1.f[0] = z2.f[0] = a->f[0] & ~0x7;
- z1.f[1] = z2.f[1] = 0;
- z2.f[0] += (1 << 3);
-
- res = 0;
- switch (RM(f)) {
- case ROUND_NEAR:
- diff1 = a->f[0] - z1.f[0];
- diff2 = z2.f[0] - a->f[0];
- if (diff1 > diff2)
- res = make_t_ieee(f, &z2, b);
- else if (diff2 > diff1)
- res = make_t_ieee(f, &z1, b);
- else
- /* equal distance: round towards even */
- if (z1.f[0] & (1 << 3))
- res = make_t_ieee(f, &z2, b);
- else
- res = make_t_ieee(f, &z1, b);
- break;
-
- case ROUND_CHOP:
- res = make_t_ieee(f, &z1, b);
- break;
-
- case ROUND_PINF:
- if (a->s) {
- res = make_t_ieee(f, &z1, b);
- } else {
- res = make_t_ieee(f, &z2, b);
- }
- break;
-
- case ROUND_NINF:
- if (a->s) {
- res = make_t_ieee(f, &z2, b);
- } else {
- res = make_t_ieee(f, &z1, b);
- }
- break;
- }
- return FPCR_INE | res;
-}
-
-
-static fpclass_t
-add_kernel_ieee (EXTENDED *op_a, EXTENDED *op_b, EXTENDED *op_c)
-{
- unsigned long mask, fa, fb, fc;
- int diff;
-
- diff = op_a->e - op_b->e;
- fa = op_a->f[0];
- fb = op_b->f[0];
- if (diff < 0) {
- diff = -diff;
- op_c->e = op_b->e;
- mask = (1UL << diff) - 1;
- fa >>= diff;
- if (op_a->f[0] & mask) {
- fa |= 1; /* set sticky bit */
- }
- } else {
- op_c->e = op_a->e;
- mask = (1UL << diff) - 1;
- fb >>= diff;
- if (op_b->f[0] & mask) {
- fb |= 1; /* set sticky bit */
- }
- }
- if (op_a->s)
- fa = -fa;
- if (op_b->s)
- fb = -fb;
- fc = fa + fb;
- op_c->f[1] = 0;
- op_c->s = fc >> 63;
- if (op_c->s) {
- fc = -fc;
- }
- op_c->f[0] = fc;
- normalize(op_c);
- return 0;
-}
-
-
-/*
- * converts s-floating "a" to t-floating "b".
- *
- * INPUT PARAMETERS:
- * a a s-floating number to be converted
- * f the rounding mode (ROUND_NEAR, etc. )
- * OUTPUT PARAMETERS:
- * b the t-floating number that "a" is converted to.
- * RETURN VALUE:
- * error flags - i.e., zero if no errors occurred,
- * FPCR_INV if invalid operation occurred, etc.
- */
-unsigned long
-ieee_CVTST (int f, unsigned long a, unsigned long *b)
-{
- EXTENDED temp;
- fpclass_t a_type;
-
- a_type = extend_ieee(a, &temp, SINGLE);
- if (a_type >= NaN && a_type <= INFTY) {
- *b = a;
- if (a_type == NaN) {
- *b |= (1UL << 51); /* turn SNaN into QNaN */
- return FPCR_INV;
- }
- return 0;
- }
- return round_t_ieee(f, &temp, b);
-}
-
-
-/*
- * converts t-floating "a" to s-floating "b".
- *
- * INPUT PARAMETERS:
- * a a t-floating number to be converted
- * f the rounding mode (ROUND_NEAR, etc. )
- * OUTPUT PARAMETERS:
- * b the s-floating number that "a" is converted to.
- * RETURN VALUE:
- * error flags - i.e., zero if no errors occurred,
- * FPCR_INV if invalid operation occurred, etc.
- */
-unsigned long
-ieee_CVTTS (int f, unsigned long a, unsigned long *b)
-{
- EXTENDED temp;
- fpclass_t a_type;
-
- a_type = extend_ieee(a, &temp, DOUBLE);
- if (a_type >= NaN && a_type <= INFTY) {
- *b = a;
- if (a_type == NaN) {
- *b |= (1UL << 51); /* turn SNaN into QNaN */
- return FPCR_INV;
- }
- return 0;
- }
- return round_s_ieee(f, &temp, b);
-}
-
-
-/*
- * converts q-format (64-bit integer) "a" to s-floating "b".
- *
- * INPUT PARAMETERS:
- * a an 64-bit integer to be converted.
- * f the rounding mode (ROUND_NEAR, etc. )
- * OUTPUT PARAMETERS:
- * b the s-floating number "a" is converted to.
- * RETURN VALUE:
- * error flags - i.e., zero if no errors occurred,
- * FPCR_INV if invalid operation occurred, etc.
- */
-unsigned long
-ieee_CVTQS (int f, unsigned long a, unsigned long *b)
-{
- EXTENDED op_b;
-
- op_b.s = 0;
- op_b.f[0] = a;
- op_b.f[1] = 0;
- if (sign(a) < 0) {
- op_b.s = 1;
- op_b.f[0] = -a;
- }
- op_b.e = 55;
- normalize(&op_b);
- return round_s_ieee(f, &op_b, b);
-}
-
-
-/*
- * converts 64-bit integer "a" to t-floating "b".
- *
- * INPUT PARAMETERS:
- * a a 64-bit integer to be converted.
- * f the rounding mode (ROUND_NEAR, etc.)
- * OUTPUT PARAMETERS:
- * b the t-floating number "a" is converted to.
- * RETURN VALUE:
- * error flags - i.e., zero if no errors occurred,
- * FPCR_INV if invalid operation occurred, etc.
- */
-unsigned long
-ieee_CVTQT (int f, long a, unsigned long *b)
-{
- EXTENDED op_b;
-
- if (a != 0) {
- op_b.s = (a < 0 ? 1 : 0);
- op_b.f[0] = (a < 0 ? -a : a);
- op_b.f[1] = 0;
- op_b.e = 55;
- normalize(&op_b);
- return round_t_ieee(f, &op_b, b);
- } else {
- *b = 0;
- return 0;
- }
-}
-
-
-/*
- * converts t-floating "a" to 64-bit integer (q-format) "b".
- *
- * INPUT PARAMETERS:
- * a a t-floating number to be converted.
- * f the rounding mode (ROUND_NEAR, etc. )
- * OUTPUT PARAMETERS:
- * b the 64-bit integer "a" is converted to.
- * RETURN VALUE:
- * error flags - i.e., zero if no errors occurred,
- * FPCR_INV if invalid operation occurred, etc.
- */
-unsigned long
-ieee_CVTTQ (int f, unsigned long a, unsigned long *pb)
-{
- unsigned int midway;
- unsigned long ov, uv, res, b;
- fpclass_t a_type;
- EXTENDED temp;
-
- a_type = extend_ieee(a, &temp, DOUBLE);
-
- b = 0x7fffffffffffffff;
- res = FPCR_INV;
- if (a_type == NaN || a_type == INFTY)
- goto out;
-
- res = 0;
- if (a_type == QNaN)
- goto out;
-
- if (temp.e > 0) {
- ov = 0;
- while (temp.e > 0) {
- --temp.e;
- ov |= temp.f[1] >> 63;
- sll128(temp.f);
- }
- if (ov || (temp.f[1] & 0xffc0000000000000))
- res |= FPCR_IOV | FPCR_INE;
- }
- else if (temp.e < 0) {
- while (temp.e < 0) {
- ++temp.e;
- uv = temp.f[0] & 1; /* save sticky bit */
- srl128(temp.f);
- temp.f[0] |= uv;
- }
- }
- b = (temp.f[1] << 9) | (temp.f[0] >> 55);
-
- /*
- * Notice: the fraction is only 52 bits long. Thus, rounding
- * cannot possibly result in an integer overflow.
- */
- switch (RM(f)) {
- case ROUND_NEAR:
- if (temp.f[0] & 0x0040000000000000) {
- midway = (temp.f[0] & 0x003fffffffffffff) == 0;
- if ((midway && (temp.f[0] & 0x0080000000000000)) ||
- !midway)
- ++b;
- }
- break;
-
- case ROUND_PINF:
- b += ((temp.f[0] & 0x007fffffffffffff) != 0 && !temp.s);
- break;
-
- case ROUND_NINF:
- b += ((temp.f[0] & 0x007fffffffffffff) != 0 && temp.s);
- break;
-
- case ROUND_CHOP:
- /* no action needed */
- break;
- }
- if ((temp.f[0] & 0x007fffffffffffff) != 0)
- res |= FPCR_INE;
-
- if (temp.s) {
- b = -b;
- }
-
-out:
- *pb = b;
- return res;
-}
-
-
-unsigned long
-ieee_CMPTEQ (unsigned long a, unsigned long b, unsigned long *c)
-{
- EXTENDED op_a, op_b;
- fpclass_t a_type, b_type;
-
- *c = 0;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if ((op_a.e == op_b.e && op_a.s == op_b.s &&
- op_a.f[0] == op_b.f[0] && op_a.f[1] == op_b.f[1]) ||
- (a_type == ZERO && b_type == ZERO))
- *c = 0x4000000000000000;
- return 0;
-}
-
-
-unsigned long
-ieee_CMPTLT (unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b;
-
- *c = 0;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if ((op_a.s == 1 && op_b.s == 0 &&
- (a_type != ZERO || b_type != ZERO)) ||
- (op_a.s == 1 && op_b.s == 1 &&
- (op_a.e > op_b.e || (op_a.e == op_b.e &&
- cmp128(op_a.f, op_b.f) > 0))) ||
- (op_a.s == 0 && op_b.s == 0 &&
- (op_a.e < op_b.e || (op_a.e == op_b.e &&
- cmp128(op_a.f,op_b.f) < 0))))
- *c = 0x4000000000000000;
- return 0;
-}
-
-
-unsigned long
-ieee_CMPTLE (unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b;
-
- *c = 0;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if ((a_type == ZERO && b_type == ZERO) ||
- (op_a.s == 1 && op_b.s == 0) ||
- (op_a.s == 1 && op_b.s == 1 &&
- (op_a.e > op_b.e || (op_a.e == op_b.e &&
- cmp128(op_a.f,op_b.f) >= 0))) ||
- (op_a.s == 0 && op_b.s == 0 &&
- (op_a.e < op_b.e || (op_a.e == op_b.e &&
- cmp128(op_a.f,op_b.f) <= 0))))
- *c = 0x4000000000000000;
- return 0;
-}
-
-
-unsigned long
-ieee_CMPTUN (unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b;
-
- *c = 0x4000000000000000;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
- *c = 0;
- return 0;
-}
-
-
-/*
- * Add a + b = c, where a, b, and c are ieee s-floating numbers. "f"
- * contains the rounding mode etc.
- */
-unsigned long
-ieee_ADDS (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- a_type = extend_ieee(a, &op_a, SINGLE);
- b_type = extend_ieee(b, &op_b, SINGLE);
- if ((a_type >= NaN && a_type <= INFTY) ||
- (b_type >= NaN && b_type <= INFTY))
- {
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if (a_type == INFTY && b_type == INFTY && sign(a) != sign(b)) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- if (a_type == INFTY)
- *c = a;
- else
- *c = b;
- return 0;
- }
-
- add_kernel_ieee(&op_a, &op_b, &op_c);
- /* special case for -0 + -0 ==> -0 */
- if (a_type == ZERO && b_type == ZERO)
- op_c.s = op_a.s && op_b.s;
- return round_s_ieee(f, &op_c, c);
-}
-
-
-/*
- * Add a + b = c, where a, b, and c are ieee t-floating numbers. "f"
- * contains the rounding mode etc.
- */
-unsigned long
-ieee_ADDT (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if ((a_type >= NaN && a_type <= INFTY) ||
- (b_type >= NaN && b_type <= INFTY))
- {
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if (a_type == INFTY && b_type == INFTY && sign(a) != sign(b)) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- if (a_type == INFTY)
- *c = a;
- else
- *c = b;
- return 0;
- }
- add_kernel_ieee(&op_a, &op_b, &op_c);
- /* special case for -0 + -0 ==> -0 */
- if (a_type == ZERO && b_type == ZERO)
- op_c.s = op_a.s && op_b.s;
-
- return round_t_ieee(f, &op_c, c);
-}
-
-
-/*
- * Subtract a - b = c, where a, b, and c are ieee s-floating numbers.
- * "f" contains the rounding mode etc.
- */
-unsigned long
-ieee_SUBS (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- a_type = extend_ieee(a, &op_a, SINGLE);
- b_type = extend_ieee(b, &op_b, SINGLE);
- if ((a_type >= NaN && a_type <= INFTY) ||
- (b_type >= NaN && b_type <= INFTY))
- {
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if (a_type == INFTY && b_type == INFTY && sign(a) == sign(b)) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- if (a_type == INFTY)
- *c = a;
- else
- *c = b ^ (1UL << 63);
- return 0;
- }
- op_b.s = !op_b.s;
- add_kernel_ieee(&op_a, &op_b, &op_c);
- /* special case for -0 - +0 ==> -0 */
- if (a_type == ZERO && b_type == ZERO)
- op_c.s = op_a.s && op_b.s;
-
- return round_s_ieee(f, &op_c, c);
-}
-
-
-/*
- * Subtract a - b = c, where a, b, and c are ieee t-floating numbers.
- * "f" contains the rounding mode etc.
- */
-unsigned long
-ieee_SUBT (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if ((a_type >= NaN && a_type <= INFTY) ||
- (b_type >= NaN && b_type <= INFTY))
- {
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if (a_type == INFTY && b_type == INFTY && sign(a) == sign(b)) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- if (a_type == INFTY)
- *c = a;
- else
- *c = b ^ (1UL << 63);
- return 0;
- }
- op_b.s = !op_b.s;
- add_kernel_ieee(&op_a, &op_b, &op_c);
- /* special case for -0 - +0 ==> -0 */
- if (a_type == ZERO && b_type == ZERO)
- op_c.s = op_a.s && op_b.s;
-
- return round_t_ieee(f, &op_c, c);
-}
-
-
-/*
- * Multiply a x b = c, where a, b, and c are ieee s-floating numbers.
- * "f" contains the rounding mode.
- */
-unsigned long
-ieee_MULS (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- a_type = extend_ieee(a, &op_a, SINGLE);
- b_type = extend_ieee(b, &op_b, SINGLE);
- if ((a_type >= NaN && a_type <= INFTY) ||
- (b_type >= NaN && b_type <= INFTY))
- {
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if ((a_type == INFTY && b_type == ZERO) ||
- (b_type == INFTY && a_type == ZERO))
- {
- *c = IEEE_QNaN; /* return canonical QNaN */
- return FPCR_INV;
- }
- if (a_type == INFTY)
- *c = a ^ ((b >> 63) << 63);
- else if (b_type == INFTY)
- *c = b ^ ((a >> 63) << 63);
- else
- /* either of a and b are +/-0 */
- *c = ((unsigned long) op_a.s ^ op_b.s) << 63;
- return 0;
- }
- op_c.s = op_a.s ^ op_b.s;
- op_c.e = op_a.e + op_b.e - 55;
- mul64(op_a.f[0], op_b.f[0], op_c.f);
-
- return round_s_ieee(f, &op_c, c);
-}
-
-
-/*
- * Multiply a x b = c, where a, b, and c are ieee t-floating numbers.
- * "f" contains the rounding mode.
- */
-unsigned long
-ieee_MULT (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- *c = IEEE_QNaN;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if ((a_type >= NaN && a_type <= ZERO) ||
- (b_type >= NaN && b_type <= ZERO))
- {
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- if ((a_type == INFTY && b_type == ZERO) ||
- (b_type == INFTY && a_type == ZERO))
- {
- *c = IEEE_QNaN; /* return canonical QNaN */
- return FPCR_INV;
- }
- if (a_type == INFTY)
- *c = a ^ ((b >> 63) << 63);
- else if (b_type == INFTY)
- *c = b ^ ((a >> 63) << 63);
- else
- /* either of a and b are +/-0 */
- *c = ((unsigned long) op_a.s ^ op_b.s) << 63;
- return 0;
- }
- op_c.s = op_a.s ^ op_b.s;
- op_c.e = op_a.e + op_b.e - 55;
- mul64(op_a.f[0], op_b.f[0], op_c.f);
-
- return round_t_ieee(f, &op_c, c);
-}
-
-
-/*
- * Divide a / b = c, where a, b, and c are ieee s-floating numbers.
- * "f" contains the rounding mode etc.
- */
-unsigned long
-ieee_DIVS (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- a_type = extend_ieee(a, &op_a, SINGLE);
- b_type = extend_ieee(b, &op_b, SINGLE);
- if ((a_type >= NaN && a_type <= ZERO) ||
- (b_type >= NaN && b_type <= ZERO))
- {
- unsigned long res;
-
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- res = 0;
- *c = IEEE_PINF;
- if (a_type == INFTY) {
- if (b_type == INFTY) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- } else if (b_type == ZERO) {
- if (a_type == ZERO) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- res = FPCR_DZE;
- } else
- /* a_type == ZERO || b_type == INFTY */
- *c = 0;
- *c |= (unsigned long) (op_a.s ^ op_b.s) << 63;
- return res;
- }
- op_c.s = op_a.s ^ op_b.s;
- op_c.e = op_a.e - op_b.e;
-
- op_a.f[1] = op_a.f[0];
- op_a.f[0] = 0;
- div128(op_a.f, op_b.f, op_c.f);
- if (a_type != ZERO)
- /* force a sticky bit because DIVs never hit exact .5: */
- op_c.f[0] |= STICKY_S;
- normalize(&op_c);
- op_c.e -= 9; /* remove excess exp from original shift */
- return round_s_ieee(f, &op_c, c);
-}
-
-
-/*
- * Divide a/b = c, where a, b, and c are ieee t-floating numbers. "f"
- * contains the rounding mode etc.
- */
-unsigned long
-ieee_DIVT (int f, unsigned long a, unsigned long b, unsigned long *c)
-{
- fpclass_t a_type, b_type;
- EXTENDED op_a, op_b, op_c;
-
- *c = IEEE_QNaN;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- b_type = extend_ieee(b, &op_b, DOUBLE);
- if ((a_type >= NaN && a_type <= ZERO) ||
- (b_type >= NaN && b_type <= ZERO))
- {
- unsigned long res;
-
- /* propagate NaNs according to arch. ref. handbook: */
- if (b_type == QNaN)
- *c = b;
- else if (b_type == NaN)
- *c = b | (1UL << 51);
- else if (a_type == QNaN)
- *c = a;
- else if (a_type == NaN)
- *c = a | (1UL << 51);
-
- if (a_type == NaN || b_type == NaN)
- return FPCR_INV;
- if (a_type == QNaN || b_type == QNaN)
- return 0;
-
- res = 0;
- *c = IEEE_PINF;
- if (a_type == INFTY) {
- if (b_type == INFTY) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- } else if (b_type == ZERO) {
- if (a_type == ZERO) {
- *c = IEEE_QNaN;
- return FPCR_INV;
- }
- res = FPCR_DZE;
- } else
- /* a_type == ZERO || b_type == INFTY */
- *c = 0;
- *c |= (unsigned long) (op_a.s ^ op_b.s) << 63;
- return res;
- }
- op_c.s = op_a.s ^ op_b.s;
- op_c.e = op_a.e - op_b.e;
-
- op_a.f[1] = op_a.f[0];
- op_a.f[0] = 0;
- div128(op_a.f, op_b.f, op_c.f);
- if (a_type != ZERO)
- /* force a sticky bit because DIVs never hit exact .5 */
- op_c.f[0] |= STICKY_T;
- normalize(&op_c);
- op_c.e -= 9; /* remove excess exp from original shift */
- return round_t_ieee(f, &op_c, c);
-}
-
-/*
- * Sqrt a = b, where a and b are ieee s-floating numbers. "f"
- * contains the rounding mode etc.
- */
-unsigned long
-ieee_SQRTS (int f, unsigned long a, unsigned long *b)
-{
- fpclass_t a_type;
- EXTENDED op_a, op_b;
-
- *b = IEEE_QNaN;
- a_type = extend_ieee(a, &op_a, SINGLE);
- if (op_a.s == 0) {
- /* FIXME -- handle positive denormals. */
- send_sig(SIGFPE, current, 1);
- }
- return FPCR_INV;
-}
-
-/*
- * Sqrt a = b, where a and b are ieee t-floating numbers. "f"
- * contains the rounding mode etc.
- */
-unsigned long
-ieee_SQRTT (int f, unsigned long a, unsigned long *b)
-{
- fpclass_t a_type;
- EXTENDED op_a, op_b;
-
- *b = IEEE_QNaN;
- a_type = extend_ieee(a, &op_a, DOUBLE);
- if (op_a.s == 0) {
- /* FIXME -- handle positive denormals. */
- send_sig(SIGFPE, current, 1);
- }
- return FPCR_INV;
-}
diff --git a/arch/alpha/math-emu/ieee-math.h b/arch/alpha/math-emu/ieee-math.h
deleted file mode 100644
index 076a6d1c8..000000000
--- a/arch/alpha/math-emu/ieee-math.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 1992,1995 by
- * Digital Equipment Corporation, Maynard, Massachusetts.
- * This file may be redistributed according to the terms of the
- * GNU General Public License.
- */
-#ifndef __ieee_math_h__
-#define __ieee_math_h__
-
-#include <asm/fpu.h>
-
-#define ROUND_SHIFT 6 /* make space for trap-enable bits */
-#define RM(f) (((f) >> ROUND_SHIFT) & 0x3)
-
-#define ROUND_CHOP (FPCR_DYN_CHOPPED >> FPCR_DYN_SHIFT)
-#define ROUND_NINF (FPCR_DYN_MINUS >> FPCR_DYN_SHIFT)
-#define ROUND_NEAR (FPCR_DYN_NORMAL >> FPCR_DYN_SHIFT)
-#define ROUND_PINF (FPCR_DYN_PLUS >> FPCR_DYN_SHIFT)
-
-extern unsigned long ieee_CVTST (int rm, unsigned long a, unsigned long *b);
-extern unsigned long ieee_CVTTS (int rm, unsigned long a, unsigned long *b);
-extern unsigned long ieee_CVTQS (int rm, unsigned long a, unsigned long *b);
-extern unsigned long ieee_CVTQT (int rm, long a, unsigned long *b);
-extern unsigned long ieee_CVTTQ (int rm, unsigned long a, unsigned long *b);
-
-extern unsigned long ieee_CMPTEQ (unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_CMPTLT (unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_CMPTLE (unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_CMPTUN (unsigned long a, unsigned long b,
- unsigned long *c);
-
-extern unsigned long ieee_ADDS (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_ADDT (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_SUBS (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_SUBT (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_MULS (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_MULT (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_DIVS (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_DIVT (int rm, unsigned long a, unsigned long b,
- unsigned long *c);
-extern unsigned long ieee_SQRTS (int rm, unsigned long a, unsigned long *b);
-extern unsigned long ieee_SQRTT (int rm, unsigned long a, unsigned long *b);
-
-#endif /* __ieee_math_h__ */
diff --git a/arch/alpha/math-emu/math.c b/arch/alpha/math-emu/math.c
new file mode 100644
index 000000000..c0ece7bcb
--- /dev/null
+++ b/arch/alpha/math-emu/math.c
@@ -0,0 +1,447 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+
+#include "sfp-util.h"
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+#include <math-emu/double.h>
+
+#define OPC_PAL 0x00
+#define OPC_INTA 0x10
+#define OPC_INTL 0x11
+#define OPC_INTS 0x12
+#define OPC_INTM 0x13
+#define OPC_FLTC 0x14
+#define OPC_FLTV 0x15
+#define OPC_FLTI 0x16
+#define OPC_FLTL 0x17
+#define OPC_MISC 0x18
+#define OPC_JSR 0x1a
+
+#define FOP_SRC_S 0
+#define FOP_SRC_T 2
+#define FOP_SRC_Q 3
+
+#define FOP_FNC_ADDx 0
+#define FOP_FNC_CVTQL 0
+#define FOP_FNC_SUBx 1
+#define FOP_FNC_MULx 2
+#define FOP_FNC_DIVx 3
+#define FOP_FNC_CMPxUN 4
+#define FOP_FNC_CMPxEQ 5
+#define FOP_FNC_CMPxLT 6
+#define FOP_FNC_CMPxLE 7
+#define FOP_FNC_SQRTx 11
+#define FOP_FNC_CVTxS 12
+#define FOP_FNC_CVTxT 14
+#define FOP_FNC_CVTxQ 15
+
+#define MISC_TRAPB 0x0000
+#define MISC_EXCB 0x0400
+
+extern unsigned long alpha_read_fp_reg (unsigned long reg);
+extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
+extern unsigned long alpha_read_fp_reg_s (unsigned long reg);
+extern void alpha_write_fp_reg_s (unsigned long reg, unsigned long val);
+
+
+#ifdef MODULE
+
+MODULE_DESCRIPTION("FP Software completion module");
+
+extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
+extern long (*alpha_fp_emul) (unsigned long pc);
+
+static long (*save_emul_imprecise)(struct pt_regs *, unsigned long);
+static long (*save_emul) (unsigned long pc);
+
+long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
+long do_alpha_fp_emul(unsigned long);
+
+int init_module(void)
+{
+ save_emul_imprecise = alpha_fp_emul_imprecise;
+ save_emul = alpha_fp_emul;
+ alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise;
+ alpha_fp_emul = do_alpha_fp_emul;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ alpha_fp_emul_imprecise = save_emul_imprecise;
+ alpha_fp_emul = save_emul;
+}
+
+#undef alpha_fp_emul_imprecise
+#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
+#undef alpha_fp_emul
+#define alpha_fp_emul do_alpha_fp_emul
+
+#endif /* MODULE */
+
+/* For 128-bit division. */
+
+void
+udiv128(unsigned long divisor_f0, unsigned long divisor_f1,
+ unsigned long dividend_f0, unsigned long dividend_f1,
+ unsigned long *quot, unsigned long *remd)
+{
+ _FP_FRAC_DECL_2(quo);
+ _FP_FRAC_DECL_2(rem);
+ _FP_FRAC_DECL_2(tmp);
+ unsigned long i, num_bits, bit;
+
+ _FP_FRAC_SET_2(rem, _FP_ZEROFRAC_2);
+ _FP_FRAC_SET_2(quo, _FP_ZEROFRAC_2);
+
+ if (_FP_FRAC_ZEROP_2(divisor))
+ goto out;
+
+ if (_FP_FRAC_GT_2(divisor, dividend)) {
+ _FP_FRAC_COPY_2(rem, dividend);
+ goto out;
+ }
+
+ if (_FP_FRAC_EQ_2(divisor, dividend)) {
+ __FP_FRAC_SET_2(quo, 0, 1);
+ goto out;
+ }
+
+ num_bits = 128;
+ while (1) {
+ bit = _FP_FRAC_NEGP_2(dividend);
+ _FP_FRAC_COPY_2(tmp, rem);
+ _FP_FRAC_SLL_2(tmp, 1);
+ _FP_FRAC_LOW_2(tmp) |= bit;
+ if (! _FP_FRAC_GE_2(tmp, divisor))
+ break;
+ _FP_FRAC_COPY_2(rem, tmp);
+ _FP_FRAC_SLL_2(dividend, 1);
+ num_bits--;
+ }
+
+ for (i = 0; i < num_bits; i++) {
+ bit = _FP_FRAC_NEGP_2(dividend);
+ _FP_FRAC_SLL_2(rem, 1);
+ _FP_FRAC_LOW_2(rem) |= bit;
+ _FP_FRAC_SUB_2(tmp, rem, divisor);
+ bit = _FP_FRAC_NEGP_2(tmp);
+ _FP_FRAC_SLL_2(dividend, 1);
+ _FP_FRAC_SLL_2(quo, 1);
+ if (!bit) {
+ _FP_FRAC_LOW_2(quo) |= 1;
+ _FP_FRAC_COPY_2(rem, tmp);
+ }
+ }
+
+out:
+ *quot = quo_f1;
+ *remd = rem_f1;
+ return;
+}
+
+/*
+ * Emulate the floating point instruction at address PC. Returns 0 if
+ * emulation fails. Notice that the kernel does not and cannot use FP
+ * regs. This is good because it means that instead of
+ * saving/restoring all fp regs, we simply stick the result of the
+ * operation into the appropriate register.
+ */
+long
+alpha_fp_emul (unsigned long pc)
+{
+ 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);
+
+ unsigned long fa, fb, fc, func, mode, src;
+ unsigned long fpcw = current->thread.flags;
+ unsigned long res, va, vb, vc, fpcr;
+ __u32 insn;
+
+ MOD_INC_USE_COUNT;
+
+ get_user(insn, (__u32*)pc);
+ fc = (insn >> 0) & 0x1f; /* destination register */
+ fb = (insn >> 16) & 0x1f;
+ fa = (insn >> 21) & 0x1f;
+ func = (insn >> 5) & 0xf;
+ src = (insn >> 9) & 0x3;
+ mode = (insn >> 11) & 0x3;
+
+ fpcr = rdfpcr();
+
+ if (mode == 3) {
+ /* Dynamic -- get rounding mode from fpcr. */
+ mode = (fpcr >> FPCR_DYN_SHIFT) & 3;
+ }
+
+ switch (src) {
+ case FOP_SRC_S:
+ va = alpha_read_fp_reg_s(fa);
+ vb = alpha_read_fp_reg_s(fb);
+
+ FP_UNPACK_SP(SA, &va);
+ FP_UNPACK_SP(SB, &vb);
+
+ switch (func) {
+ case FOP_FNC_SUBx:
+ FP_SUB_S(SR, SA, SB);
+ goto pack_s;
+
+ case FOP_FNC_ADDx:
+ FP_ADD_S(SR, SA, SB);
+ goto pack_s;
+
+ case FOP_FNC_MULx:
+ FP_MUL_S(SR, SA, SB);
+ goto pack_s;
+
+ case FOP_FNC_DIVx:
+ FP_DIV_S(SR, SA, SB);
+ goto pack_s;
+
+ case FOP_FNC_SQRTx:
+ FP_SQRT_S(SR, SB);
+ goto pack_s;
+ }
+ goto bad_insn;
+
+ case FOP_SRC_T:
+ va = alpha_read_fp_reg(fa);
+ vb = alpha_read_fp_reg(fb);
+
+ if ((func & ~3) == FOP_FNC_CMPxUN) {
+ FP_UNPACK_RAW_DP(DA, &va);
+ FP_UNPACK_RAW_DP(DB, &vb);
+ if (!DA_e && !_FP_FRAC_ZEROP_1(DA)) {
+ FP_SET_EXCEPTION(FP_EX_DENORM);
+ if (FP_DENORM_ZERO)
+ _FP_FRAC_SET_1(DA, _FP_ZEROFRAC_1);
+ }
+ if (!DB_e && !_FP_FRAC_ZEROP_1(DB)) {
+ FP_SET_EXCEPTION(FP_EX_DENORM);
+ if (FP_DENORM_ZERO)
+ _FP_FRAC_SET_1(DB, _FP_ZEROFRAC_1);
+ }
+ FP_CMP_D(res, DA, DB, 3);
+ vc = 0x4000000000000000;
+ /* CMPTEQ, CMPTUN don't trap on QNaN, while CMPTLT and CMPTLE do */
+ if (res == 3 && ((func & 3) >= 2 || FP_ISSIGNAN_D(DA) || FP_ISSIGNAN_D(DB)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ switch (func) {
+ case FOP_FNC_CMPxUN: if (res != 3) vc = 0; break;
+ case FOP_FNC_CMPxEQ: if (res) vc = 0; break;
+ case FOP_FNC_CMPxLT: if (res != -1) vc = 0; break;
+ case FOP_FNC_CMPxLE: if ((long)res > 0) vc = 0; break;
+ }
+ goto done_d;
+ }
+
+ FP_UNPACK_DP(DA, &va);
+ FP_UNPACK_DP(DB, &vb);
+
+ switch (func) {
+ case FOP_FNC_SUBx:
+ FP_SUB_D(DR, DA, DB);
+ goto pack_d;
+
+ case FOP_FNC_ADDx:
+ FP_ADD_D(DR, DA, DB);
+ goto pack_d;
+
+ case FOP_FNC_MULx:
+ FP_MUL_D(DR, DA, DB);
+ goto pack_d;
+
+ case FOP_FNC_DIVx:
+ FP_DIV_D(DR, DA, DB);
+ goto pack_d;
+
+ case FOP_FNC_SQRTx:
+ FP_SQRT_D(DR, DB);
+ goto pack_d;
+
+ case FOP_FNC_CVTxS:
+ /* It is irritating that DEC encoded CVTST with
+ SRC == T_floating. It is also interesting that
+ the bit used to tell the two apart is /U... */
+ if (insn & 0x2000) {
+ FP_CONV(S,D,1,1,SR,DB);
+ goto pack_s;
+ } else {
+ /* CVTST need do nothing else but copy the
+ bits and repack. */
+ DR_c = DB_c;
+ DR_s = DB_s;
+ DR_e = DB_e;
+ DR_f = DB_f;
+ goto pack_d;
+ }
+
+ case FOP_FNC_CVTxQ:
+ if (DB_c == FP_CLS_NAN && (_FP_FRAC_HIGH_RAW_D(DB) & _FP_QNANBIT_D))
+ vc = 0; /* AAHB Table B-2 sais QNaN should not trigger INV */
+ else
+ FP_TO_INT_ROUND_D(vc, DB, 64, 2);
+ goto done_d;
+ }
+ goto bad_insn;
+
+ case FOP_SRC_Q:
+ vb = alpha_read_fp_reg(fb);
+
+ switch (func) {
+ case FOP_FNC_CVTQL:
+ /* Notice: We can get here only due to an integer
+ overflow. Such overflows are reported as invalid
+ ops. We return the result the hw would have
+ computed. */
+ vc = ((vb & 0xc0000000) << 32 | /* sign and msb */
+ (vb & 0x3fffffff) << 29); /* rest of the int */
+ FP_SET_EXCEPTION (FP_EX_INVALID);
+ goto done_d;
+
+ case FOP_FNC_CVTxS:
+ FP_FROM_INT_S(SR, ((long)vb), 64, long);
+ goto pack_s;
+
+ case FOP_FNC_CVTxT:
+ FP_FROM_INT_D(DR, ((long)vb), 64, long);
+ goto pack_d;
+ }
+ goto bad_insn;
+ }
+ goto bad_insn;
+
+pack_s:
+ FP_PACK_SP(&vc, SR);
+ alpha_write_fp_reg_s(fc, vc);
+ goto done;
+
+pack_d:
+ FP_PACK_DP(&vc, DR);
+done_d:
+ alpha_write_fp_reg(fc, vc);
+ goto done;
+
+ /*
+ * Take the appropriate action for each possible
+ * floating-point result:
+ *
+ * - Set the appropriate bits in the FPCR
+ * - If the specified exception is enabled in the FPCR,
+ * return. The caller (entArith) will dispatch
+ * the appropriate signal to the translated program.
+ *
+ * In addition, properly track the exception state in software
+ * as described in the Alpha Architectre Handbook section 4.7.7.3.
+ */
+done:
+ if (_fex) {
+ /* Record exceptions in software control word. */
+ current->thread.flags
+ = fpcw |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
+
+ /* Update hardware control register */
+ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
+ fpcr |= ieee_swcr_to_fpcr(fpcw);
+ wrfpcr(fpcr);
+
+ /* Do we generate a signal? */
+ if (_fex & fpcw & IEEE_TRAP_ENABLE_MASK) {
+ MOD_DEC_USE_COUNT;
+ return 0;
+ }
+ }
+
+ /* We used to write the destination register here, but DEC FORTRAN
+ requires that the result *always* be written... so we do the write
+ immediately after the operations above. */
+
+ MOD_DEC_USE_COUNT;
+ return 1;
+
+bad_insn:
+ printk(KERN_ERR "alpha_fp_emul: Invalid FP insn %#x at %#lx\n",
+ insn, pc);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+long
+alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
+{
+ unsigned long trigger_pc = regs->pc - 4;
+ unsigned long insn, opcode, rc;
+
+ MOD_INC_USE_COUNT;
+
+ /*
+ * Turn off the bits corresponding to registers that are the
+ * target of instructions that set bits in the exception
+ * summary register. We have some slack doing this because a
+ * register that is the target of a trapping instruction can
+ * be written at most once in the trap shadow.
+ *
+ * Branches, jumps, TRAPBs, EXCBs and calls to PALcode all
+ * bound the trap shadow, so we need not look any further than
+ * up to the first occurrence of such an instruction.
+ */
+ while (write_mask) {
+ get_user(insn, (__u32*)(trigger_pc));
+ opcode = insn >> 26;
+ rc = insn & 0x1f;
+
+ switch (opcode) {
+ case OPC_PAL:
+ case OPC_JSR:
+ case 0x30 ... 0x3f: /* branches */
+ MOD_DEC_USE_COUNT;
+ return 0;
+
+ case OPC_MISC:
+ switch (insn & 0xffff) {
+ case MISC_TRAPB:
+ case MISC_EXCB:
+ MOD_DEC_USE_COUNT;
+ return 0;
+
+ default:
+ break;
+ }
+ break;
+
+ case OPC_INTA:
+ case OPC_INTL:
+ case OPC_INTS:
+ case OPC_INTM:
+ write_mask &= ~(1UL << rc);
+ break;
+
+ case OPC_FLTC:
+ case OPC_FLTV:
+ case OPC_FLTI:
+ case OPC_FLTL:
+ write_mask &= ~(1UL << (rc + 32));
+ break;
+ }
+ if (!write_mask) {
+ if (alpha_fp_emul(trigger_pc)) {
+ /* re-execute insns in trap-shadow: */
+ regs->pc = trigger_pc + 4;
+ MOD_DEC_USE_COUNT;
+ return 1;
+ }
+ break;
+ }
+ trigger_pc -= 4;
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
diff --git a/arch/alpha/math-emu/sfp-util.h b/arch/alpha/math-emu/sfp-util.h
new file mode 100644
index 000000000..7a6a8cf45
--- /dev/null
+++ b/arch/alpha/math-emu/sfp-util.h
@@ -0,0 +1,40 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/fpu.h>
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ ((sl) = (al) + (bl), (sh) = (ah) + (bh) + ((sl) < (al)))
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ ((sl) = (al) - (bl), (sh) = (ah) - (bh) - ((al) < (bl)))
+
+#define umul_ppmm(wh, wl, u, v) \
+ __asm__ ("mulq %2,%3,%1; umulh %2,%3,%0" \
+ : "=r" ((UDItype)(wh)), \
+ "=&r" ((UDItype)(wl)) \
+ : "r" ((UDItype)(u)), \
+ "r" ((UDItype)(v)))
+
+extern void udiv128(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long *,
+ unsigned long *);
+
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ unsigned long xr, xi; \
+ udiv128((n0), (n1), 0, (d), &xr, &xi); \
+ (q) = xr; \
+ (r) = xi; \
+ } while (0)
+
+#define UDIV_NEEDS_NORMALIZATION 1
+
+#define abort() goto bad_insn
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN -1
+#endif
+#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index dc15db08b..4da99bad2 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -11,7 +11,7 @@
#define __EXTERN_INLINE inline
#include <asm/mmu_context.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#undef __EXTERN_INLINE
#include <linux/signal.h>
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 0ec65b409..8c40bc6a2 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -4,6 +4,8 @@
* Copyright (C) 1995 Linus Torvalds
*/
+/* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */
+
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -15,6 +17,8 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/bootmem.h> /* max_low_pfn */
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
@@ -22,10 +26,12 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/hwrpb.h>
#include <asm/dma.h>
+#include <asm/mmu_context.h>
-#define DEBUG_POISON 0
+static unsigned long totalram_pages;
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
@@ -58,7 +64,7 @@ get_pmd_slow(pgd_t *pgd, unsigned long offset)
pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
if (pgd_none(*pgd)) {
if (pmd) {
- clear_page((unsigned long)pmd);
+ clear_page((void *)pmd);
pgd_set(pgd, pmd);
return pmd + offset;
}
@@ -81,7 +87,7 @@ get_pte_slow(pmd_t *pmd, unsigned long offset)
pte = (pte_t *) __get_free_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- clear_page((unsigned long)pte);
+ clear_page((void *)pte);
pmd_set(pmd, pte);
return pte + offset;
}
@@ -136,7 +142,7 @@ pte_t
__bad_page(void)
{
memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
- return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
+ return pte_mkdirty(mk_pte(mem_map + MAP_NR(EMPTY_PGE), PAGE_SHARED));
}
void
@@ -172,8 +178,6 @@ show_mem(void)
#endif
}
-extern unsigned long free_area_init(unsigned long, unsigned long);
-
static inline unsigned long
load_PCB(struct thread_struct * pcb)
{
@@ -186,40 +190,39 @@ load_PCB(struct thread_struct * pcb)
* paging_init() sets up the page tables: in the alpha version this actually
* unmaps the bootup page table (as we're now in KSEG, so we don't need it).
*/
-unsigned long
-paging_init(unsigned long start_mem, unsigned long end_mem)
+void
+paging_init(void)
{
- int i;
unsigned long newptbr;
- struct memclust_struct * cluster;
- struct memdesc_struct * memdesc;
unsigned long original_pcb_ptr;
+ unsigned int zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long dma_pfn, high_pfn;
+
+ dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ high_pfn = max_low_pfn;
+
+#define ORDER_MASK (~((1 << (MAX_ORDER-1))-1))
+#define ORDER_ALIGN(n) (((n) + ~ORDER_MASK) & ORDER_MASK)
+
+ dma_pfn = ORDER_ALIGN(dma_pfn);
+ high_pfn = ORDER_ALIGN(high_pfn);
+
+#undef ORDER_MASK
+#undef ORDER_ALIGN
- /* initialize mem_map[] */
- start_mem = free_area_init(start_mem, end_mem);
-
- /* find free clusters, update mem_map[] accordingly */
- memdesc = (struct memdesc_struct *)
- (hwrpb->mddt_offset + (unsigned long) hwrpb);
- cluster = memdesc->cluster;
- for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
- unsigned long pfn, nr;
-
- /* Bit 0 is console/PALcode reserved. Bit 1 is
- non-volatile memory -- we might want to mark
- this for later */
- if (cluster->usage & 3)
- continue;
- pfn = cluster->start_pfn;
- nr = cluster->numpages;
-
- while (nr--)
- clear_bit(PG_reserved, &mem_map[pfn++].flags);
+ if (dma_pfn > high_pfn)
+ zones_size[ZONE_DMA] = high_pfn;
+ else {
+ zones_size[ZONE_DMA] = dma_pfn;
+ zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
}
+ /* Initialize mem_map[]. */
+ free_area_init(zones_size);
+
/* Initialize the kernel's page tables. Linux puts the vptb in
the last slot of the L1 page table. */
- memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE);
+ memset((void *)ZERO_PGE, 0, PAGE_SIZE);
memset(swapper_pg_dir, 0, PAGE_SIZE);
newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
pgd_val(swapper_pg_dir[1023]) =
@@ -252,8 +255,6 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
phys_to_virt(original_pcb_ptr);
}
original_pcb = *(struct thread_struct *) original_pcb_ptr;
-
- return start_mem;
}
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
@@ -273,64 +274,42 @@ srm_paging_stop (void)
}
#endif
-#if DEBUG_POISON
-static void
-kill_page(unsigned long pg)
+static void __init printk_memory_info(void)
{
- unsigned long *p = (unsigned long *)pg;
- unsigned long i = PAGE_SIZE, v = 0xdeadbeefdeadbeef;
- do {
- p[0] = v;
- p[1] = v;
- p[2] = v;
- p[3] = v;
- p[4] = v;
- p[5] = v;
- p[6] = v;
- p[7] = v;
- i -= 64;
- p += 8;
- } while (i != 0);
+ unsigned long codesize, reservedpages, datasize, initsize, tmp;
+ extern int page_is_ram(unsigned long) __init;
+ extern char _text, _etext, _data, _edata;
+ extern char __init_begin, __init_end;
+
+ /* printk all informations */
+ reservedpages = 0;
+ for (tmp = 0; tmp < max_low_pfn; tmp++)
+ /*
+ * Only count reserved RAM pages
+ */
+ if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
+ reservedpages++;
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_text;
+ datasize = (unsigned long) &_edata - (unsigned long) &_data;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, %luk data, %luk init)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ max_mapnr << (PAGE_SHIFT-10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT-10),
+ datasize >> 10,
+ initsize >> 10);
}
-#else
-#define kill_page(pg)
-#endif
-void
-mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init
+mem_init(void)
{
- unsigned long tmp;
-
- end_mem &= PAGE_MASK;
- max_mapnr = num_physpages = MAP_NR(end_mem);
- high_memory = (void *) end_mem;
- start_mem = PAGE_ALIGN(start_mem);
-
- /*
- * Mark the pages used by the kernel as reserved.
- */
- tmp = KERNEL_START;
- while (tmp < start_mem) {
- set_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
- tmp += PAGE_SIZE;
- }
+ max_mapnr = num_physpages = max_low_pfn;
+ totalram_pages += free_all_bootmem();
- for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
- if (tmp >= MAX_DMA_ADDRESS)
- clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
- if (PageReserved(mem_map+MAP_NR(tmp)))
- continue;
- atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start && tmp >= initrd_start && tmp < initrd_end)
- continue;
-#endif
- kill_page(tmp);
- free_page(tmp);
- }
- tmp = nr_free_pages << PAGE_SHIFT;
- printk("Memory: %luk available\n", tmp >> 10);
- return;
+ printk_memory_info();
}
void
@@ -341,34 +320,37 @@ free_initmem (void)
addr = (unsigned long)(&__init_begin);
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
- mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
- atomic_set(&mem_map[MAP_NR(addr)].count, 1);
- kill_page(addr);
+ ClearPageReserved(mem_map + MAP_NR(addr));
+ set_page_count(mem_map+MAP_NR(addr), 1);
free_page(addr);
+ totalram_pages++;
}
printk ("Freeing unused kernel memory: %ldk freed\n",
(&__init_end - &__init_begin) >> 10);
}
+#ifdef CONFIG_BLK_DEV_INITRD
void
-si_meminfo(struct sysinfo *val)
+free_initrd_mem(unsigned long start, unsigned long end)
{
- int i;
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(mem_map + MAP_NR(start));
+ set_page_count(mem_map+MAP_NR(start), 1);
+ free_page(start);
+ totalram_pages++;
+ }
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+}
+#endif
- i = max_mapnr;
- val->totalram = 0;
+void
+si_meminfo(struct sysinfo *val)
+{
+ val->totalram = totalram_pages;
val->sharedram = 0;
- val->freeram = nr_free_pages << PAGE_SHIFT;
- val->bufferram = atomic_read(&buffermem);
- while (i-- > 0) {
- if (PageReserved(mem_map+i))
- continue;
- val->totalram++;
- if (!atomic_read(&mem_map[i].count))
- continue;
- val->sharedram += atomic_read(&mem_map[i].count) - 1;
- }
- val->totalram <<= PAGE_SHIFT;
- val->sharedram <<= PAGE_SHIFT;
- return;
+ val->freeram = nr_free_pages();
+ val->bufferram = atomic_read(&buffermem_pages);
+ val->totalhigh = 0;
+ val->freehigh = 0;
+ val->mem_unit = PAGE_SIZE;
}