summaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /arch/alpha
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff)
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine status unknown.
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/boot/bootp.c18
-rw-r--r--arch/alpha/boot/main.c17
-rw-r--r--arch/alpha/config.in44
-rw-r--r--arch/alpha/defconfig6
-rw-r--r--arch/alpha/kernel/Makefile25
-rw-r--r--arch/alpha/kernel/console.c65
-rw-r--r--arch/alpha/kernel/core_mcpcia.c83
-rw-r--r--arch/alpha/kernel/core_titan.c486
-rw-r--r--arch/alpha/kernel/core_tsunami.c26
-rw-r--r--arch/alpha/kernel/core_wildfire.c668
-rw-r--r--arch/alpha/kernel/entry.S7
-rw-r--r--arch/alpha/kernel/irq.c8
-rw-r--r--arch/alpha/kernel/irq_alpha.c12
-rw-r--r--arch/alpha/kernel/irq_i8259.c2
-rw-r--r--arch/alpha/kernel/machvec_impl.h13
-rw-r--r--arch/alpha/kernel/osf_sys.c4
-rw-r--r--arch/alpha/kernel/pci.c19
-rw-r--r--arch/alpha/kernel/pci_iommu.c17
-rw-r--r--arch/alpha/kernel/proto.h20
-rw-r--r--arch/alpha/kernel/ptrace.c45
-rw-r--r--arch/alpha/kernel/setup.c217
-rw-r--r--arch/alpha/kernel/signal.c2
-rw-r--r--arch/alpha/kernel/smc37c669.c3
-rw-r--r--arch/alpha/kernel/smp.c23
-rw-r--r--arch/alpha/kernel/sys_dp264.c11
-rw-r--r--arch/alpha/kernel/sys_mikasa.c4
-rw-r--r--arch/alpha/kernel/sys_titan.c392
-rw-r--r--arch/alpha/kernel/sys_wildfire.c362
-rw-r--r--arch/alpha/kernel/traps.c239
-rw-r--r--arch/alpha/lib/Makefile7
-rw-r--r--arch/alpha/lib/callback_init.c79
-rw-r--r--arch/alpha/lib/callback_srm.S102
-rw-r--r--arch/alpha/lib/srm_dispatch.S43
-rw-r--r--arch/alpha/lib/srm_fixup.S42
-rw-r--r--arch/alpha/lib/srm_printk.c34
-rw-r--r--arch/alpha/lib/srm_puts.c33
-rw-r--r--arch/alpha/mm/extable.c42
-rw-r--r--arch/alpha/mm/fault.c6
-rw-r--r--arch/alpha/mm/init.c67
-rw-r--r--arch/alpha/vmlinux.lds6
40 files changed, 2992 insertions, 307 deletions
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
index bb892ba3c..3be5fd6b6 100644
--- a/arch/alpha/boot/bootp.c
+++ b/arch/alpha/boot/bootp.c
@@ -93,7 +93,7 @@ pal_init(void)
i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
if (i) {
srm_printk("failed, code %ld\n", i);
- halt();
+ __halt();
}
percpu = (struct percpu_struct *)
@@ -171,8 +171,7 @@ start_kernel(void)
srm_printk("Initrd positioned at %#lx\n", initrd_start);
#endif
- nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
- envval, sizeof(envval));
+ nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
if (nbytes < 0 || nbytes >= sizeof(envval)) {
nbytes = 0;
}
@@ -181,18 +180,17 @@ start_kernel(void)
/* NOTE: *no* callbacks or printouts from here on out!!! */
- /*
- * This is a hack, as some consoles seem to get virtual 20000000
- * (ie where the SRM console puts the kernel bootp image) memory
- * overlapping physical 310000 memory, which causes real problems
- * when attempting to copy the former to the latter... :-(
+ /* This is a hack, as some consoles seem to get virtual 20000000 (ie
+ * where the SRM console puts the kernel bootp image) memory
+ * overlapping physical memory where the kernel wants to be put,
+ * which causes real problems when attempting to copy the former to
+ * the latter... :-(
*
* So, we first move the kernel virtual-to-physical way above where
* we physically want the kernel to end up, then copy it from there
* to its final resting place... ;-}
*
- * Sigh...
- */
+ * Sigh... */
#ifdef INITRD_SIZE
load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_SIZE);
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c
index 07913d899..78c9b0b6e 100644
--- a/arch/alpha/boot/main.c
+++ b/arch/alpha/boot/main.c
@@ -90,7 +90,7 @@ pal_init(void)
i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
if (i) {
srm_printk("failed, code %ld\n", i);
- halt();
+ __halt();
}
percpu = (struct percpu_struct *)
@@ -107,15 +107,15 @@ static inline long openboot(void)
char bootdev[256];
long result;
- result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
+ result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
if (result < 0)
return result;
- return srm_dispatch(CCB_OPEN, bootdev, result & 255);
+ return callback_open(bootdev, result & 255);
}
static inline long close(long dev)
{
- return srm_dispatch(CCB_CLOSE, dev);
+ return callback_close(dev);
}
static inline long load(long dev, unsigned long addr, unsigned long count)
@@ -124,7 +124,7 @@ static inline long load(long dev, unsigned long addr, unsigned long count)
extern char _end;
long result, boot_size = &_end - (char *) BOOT_ADDR;
- result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
+ result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
if (result < 0)
return result;
result &= 255;
@@ -132,7 +132,7 @@ static inline long load(long dev, unsigned long addr, unsigned long count)
if (result)
srm_printk("Boot file specification (%s) not implemented\n",
bootfile);
- return srm_dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1);
+ return callback_read(dev, count, addr, boot_size/512 + 1);
}
/*
@@ -176,8 +176,7 @@ void start_kernel(void)
return;
}
- nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
- envval, sizeof(envval));
+ nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
if (nbytes < 0) {
nbytes = 0;
}
@@ -188,5 +187,5 @@ void start_kernel(void)
runkernel();
for (i = 0 ; i < 0x100000000 ; i++)
/* nothing */;
- halt();
+ __halt();
}
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index 6053ae25c..5f344e0f5 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -1,6 +1,6 @@
#
# For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
#
define_bool CONFIG_UID16 n
@@ -51,7 +51,9 @@ choice 'Alpha system type' \
RX164 CONFIG_ALPHA_RX164 \
SX164 CONFIG_ALPHA_SX164 \
Sable CONFIG_ALPHA_SABLE \
- Takara CONFIG_ALPHA_TAKARA" Generic
+ Takara CONFIG_ALPHA_TAKARA \
+ Titan CONFIG_ALPHA_TITAN \
+ Wildfire CONFIG_ALPHA_WILDFIRE" Generic
# clear all implied options (don't want default values for those):
unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
@@ -131,6 +133,16 @@ then
define_bool CONFIG_ALPHA_EV6 y
define_bool CONFIG_ALPHA_TSUNAMI y
fi
+if [ "$CONFIG_ALPHA_WILDFIRE" = "y" ]
+then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_EV6 y
+fi
+if [ "$CONFIG_ALPHA_TITAN" = "y" ]
+then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_EV6 y
+fi
if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ]
then
define_bool CONFIG_ALPHA_EV5 y
@@ -151,18 +163,23 @@ then
define_bool CONFIG_ALPHA_IRONGATE y
fi
+if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
+ -o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_NORITAKE" = "y" \
+ -o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" \
+ -o "$CONFIG_ALPHA_EIGER" = "y" -o "$CONFIG_ALPHA_WILDFIRE" = "y" \
+ -o "$CONFIG_ALPHA_TITAN" = "y" ]
+then
+ define_bool CONFIG_ALPHA_SRM y
+fi
if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
- -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \
+ -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \
-o "$CONFIG_ALPHA_TAKARA" = "y" -o "$CONFIG_ALPHA_EB164" = "y" \
- -o "$CONFIG_ALPHA_MIKASA" = "y" -o "$CONFIG_ALPHA_ALCOR" = "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_EIGER" = "y" ]
+ -o "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \
+ -o "$CONFIG_ALPHA_LX164" = "y" -o "$CONFIG_ALPHA_SX164" = "y" ]
then
bool 'Use SRM as bootloader' CONFIG_ALPHA_SRM
fi
+
if [ "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
-o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_NORITAKE" = "y" \
-o "$CONFIG_ALPHA_RAWHIDE" = "y" ]
@@ -179,7 +196,8 @@ then
fi
if [ "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" \
- -o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_GENERIC" = "y" ]
+ -o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_WILDFIRE" = "y" \
+ -o "$CONFIG_ALPHA_TITAN" = "y" -o "$CONFIG_ALPHA_GENERIC" = "y" ]
then
bool 'Symmetric multi-processing support' CONFIG_SMP
fi
@@ -286,6 +304,12 @@ if [ "$CONFIG_VT" = "y" ]; then
mainmenu_option next_comment
comment 'Console drivers'
bool 'VGA text console' CONFIG_VGA_CONSOLE
+# if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then
+# bool ' Allow VGA on any bus?' CONFIG_VGA_HOSE
+# if [ "$CONFIG_VGA_HOSE" = "y" ]; then
+# define_bool CONFIG_DUMMY_CONSOLE y
+# fi
+# fi
source drivers/video/Config.in
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_PCI_CONSOLE y
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 37d7a8630..f7bf7b2a0 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -45,6 +45,8 @@ CONFIG_ALPHA_GENERIC=y
# CONFIG_ALPHA_SX164 is not set
# CONFIG_ALPHA_SABLE is not set
# CONFIG_ALPHA_TAKARA is not set
+# CONFIG_ALPHA_TITAN is not set
+# CONFIG_ALPHA_WILDFIRE is not set
CONFIG_ISA=y
# CONFIG_SBUS is not set
CONFIG_PCI=y
@@ -83,10 +85,6 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 3a0a4ec0b..3b8d98bd2 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -26,17 +26,22 @@ O_OBJS += smp.o irq_smp.o
endif
ifdef CONFIG_PCI
-L_OBJS += pci.o pci_iommu.o
+O_OBJS += pci.o pci_iommu.o
+endif
+
+ifdef CONFIG_VGA_HOSE
+L_OBJS += console.o
endif
ifdef CONFIG_ALPHA_GENERIC
O_OBJS += core_apecs.o core_cia.o core_irongate.o core_lca.o core_mcpcia.o \
- core_polaris.o core_t2.o core_tsunami.o \
+ core_polaris.o core_t2.o core_tsunami.o core_titan.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_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o sys_titan.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
+ sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o \
+ sys_wildfire.o core_wildfire.o
else
@@ -62,9 +67,15 @@ endif
ifdef CONFIG_ALPHA_TSUNAMI
O_OBJS += core_tsunami.o
endif
+ifdef CONFIG_ALPHA_TITAN
+O_OBJS += core_titan.o
+endif
ifdef CONFIG_ALPHA_POLARIS
O_OBJS += core_polaris.o
endif
+ifdef CONFIG_ALPHA_WILDFIRE
+O_OBJS += core_wildfire.o
+endif
# Board support
ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),)
@@ -76,6 +87,9 @@ endif
ifdef CONFIG_ALPHA_DP264
O_OBJS += sys_dp264.o
endif
+ifdef CONFIG_ALPHA_TITAN
+O_OBJS += sys_titan.o
+endif
ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
O_OBJS += sys_eb64p.o
endif
@@ -118,6 +132,9 @@ endif
ifdef CONFIG_ALPHA_TAKARA
O_OBJS += sys_takara.o
endif
+ifdef CONFIG_ALPHA_WILDFIRE
+O_OBJS += sys_wildfire.o
+endif
endif # GENERIC
diff --git a/arch/alpha/kernel/console.c b/arch/alpha/kernel/console.c
new file mode 100644
index 000000000..ac2e49817
--- /dev/null
+++ b/arch/alpha/kernel/console.c
@@ -0,0 +1,65 @@
+/*
+ * linux/arch/alpha/kernel/console.c
+ *
+ * Architecture-specific specific support for VGA device on
+ * non-0 I/O hose
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <asm/vga.h>
+#include <asm/machvec.h>
+
+#ifdef CONFIG_VGA_HOSE
+
+/*
+ * Externally-visible vga hose bases
+ */
+unsigned long __vga_hose_io_base = 0; /* base for default hose */
+unsigned long __vga_hose_mem_base = 0; /* base for default hose */
+
+static struct pci_controler * __init
+default_vga_hose_select(struct pci_controler *h1, struct pci_controler *h2)
+{
+ if (h2->index < h1->index)
+ return h2;
+
+ return h1;
+}
+
+void __init
+set_vga_hose(struct pci_controler *hose)
+{
+ if (hose) {
+ __vga_hose_io_base = hose->io_space->start;
+ __vga_hose_mem_base = hose->mem_space->start;
+ }
+}
+
+void __init
+locate_and_init_vga(void *(*sel_func)(void *, void *))
+{
+ struct pci_controler *hose = NULL;
+ struct pci_dev *dev = NULL;
+
+ if (!sel_func) sel_func = (void *)default_vga_hose_select;
+
+ for(dev=NULL; (dev=pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) {
+ if (!hose) hose = dev->sysdata;
+ else hose = sel_func(hose, dev->sysdata);
+ }
+
+ /* Did we already inititialize the correct one? */
+ if (conswitchp == &vga_con &&
+ __vga_hose_io_base == hose->io_space->start &&
+ __vga_hose_mem_base == hose->mem_space->start)
+ return;
+
+ /* Set the VGA hose and init the new console */
+ set_vga_hose(hose);
+ take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1);
+}
+
+#endif
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
index 527c4f5eb..648090d24 100644
--- a/arch/alpha/kernel/core_mcpcia.c
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -45,6 +45,8 @@
#define MCPCIA_MAX_HOSES 4
+static int mcpcia_hose_count; /* Actual number found. */
+
/*
* Given a bus, device, and function number, compute resulting
* configuration space address and setup the MCPCIA_HAXR2 register
@@ -308,6 +310,7 @@ mcpcia_probe_hose(int h)
mb();
draina();
wrmces(7);
+
mcheck_expected(cpu) = 2; /* indicates probing */
mcheck_taken(cpu) = 0;
mcheck_extra(cpu) = mid;
@@ -410,18 +413,19 @@ mcpcia_startup_hose(struct pci_controler *hose)
* ??? We ought to scale window 1 with memory.
*/
- hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
- hose->sg_pci = iommu_arena_new(hose, 0x40000000, 0x08000000, 0);
+ /* Make sure to align the arenas. */
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 1);
+ hose->sg_pci = iommu_arena_new(hose, 0x40000000, 0x08000000, 1);
__direct_map_base = 0x80000000;
__direct_map_size = 0x80000000;
*(vuip)MCPCIA_W0_BASE(mid) = hose->sg_isa->dma_base | 3;
*(vuip)MCPCIA_W0_MASK(mid) = (hose->sg_isa->size - 1) & 0xfff00000;
- *(vuip)MCPCIA_T0_BASE(mid) = virt_to_phys(hose->sg_isa->ptes) >> 2;
+ *(vuip)MCPCIA_T0_BASE(mid) = virt_to_phys(hose->sg_isa->ptes) >> 8;
*(vuip)MCPCIA_W1_BASE(mid) = hose->sg_pci->dma_base | 3;
*(vuip)MCPCIA_W1_MASK(mid) = (hose->sg_pci->size - 1) & 0xfff00000;
- *(vuip)MCPCIA_T1_BASE(mid) = virt_to_phys(hose->sg_pci->ptes) >> 2;
+ *(vuip)MCPCIA_T1_BASE(mid) = virt_to_phys(hose->sg_pci->ptes) >> 8;
*(vuip)MCPCIA_W2_BASE(mid) = __direct_map_base | 1;
*(vuip)MCPCIA_W2_MASK(mid) = (__direct_map_size - 1) & 0xfff00000;
@@ -464,18 +468,20 @@ void __init
mcpcia_init_hoses(void)
{
struct pci_controler *hose;
- int h, hose_count = 0;
+ int h;
+
+ mcpcia_hose_count = 0;
/* First, find how many hoses we have. */
for (h = 0; h < MCPCIA_MAX_HOSES; ++h) {
if (mcpcia_probe_hose(h)) {
if (h != 0)
mcpcia_new_hose(h);
- hose_count++;
+ mcpcia_hose_count++;
}
}
- printk("mcpcia_init_hoses: found %d hoses\n", hose_count);
+ printk("mcpcia_init_hoses: found %d hoses\n", mcpcia_hose_count);
/* Now do init for each hose. */
for (hose = hose_head; hose; hose = hose->next)
@@ -554,6 +560,65 @@ mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
frame->ld_lock);
}
+static void
+mcpcia_print_system_area(unsigned long la_ptr)
+{
+ struct el_common *frame;
+ int i;
+
+ struct IOD_subpacket {
+ unsigned long base;
+ unsigned int whoami;
+ unsigned int rsvd1;
+ unsigned int pci_rev;
+ unsigned int cap_ctrl;
+ unsigned int hae_mem;
+ unsigned int hae_io;
+ unsigned int int_ctl;
+ unsigned int int_reg;
+ unsigned int int_mask0;
+ unsigned int int_mask1;
+ unsigned int mc_err0;
+ unsigned int mc_err1;
+ unsigned int cap_err;
+ unsigned int rsvd2;
+ unsigned int pci_err1;
+ unsigned int mdpa_stat;
+ unsigned int mdpa_syn;
+ unsigned int mdpb_stat;
+ unsigned int mdpb_syn;
+ unsigned int rsvd3;
+ unsigned int rsvd4;
+ unsigned int rsvd5;
+ } *iodpp;
+
+ frame = (struct el_common *)la_ptr;
+
+ iodpp = (struct IOD_subpacket *) (la_ptr + frame->sys_offset);
+
+ for (i = 0; i < mcpcia_hose_count; i++, iodpp++) {
+ printk("IOD %d Register Subpacket - Bridge Base Address %16lx\n",
+ i, iodpp->base);
+ printk(" WHOAMI = %8x\n", iodpp->whoami);
+ printk(" PCI_REV = %8x\n", iodpp->pci_rev);
+ printk(" CAP_CTRL = %8x\n", iodpp->cap_ctrl);
+ printk(" HAE_MEM = %8x\n", iodpp->hae_mem);
+ printk(" HAE_IO = %8x\n", iodpp->hae_io);
+ printk(" INT_CTL = %8x\n", iodpp->int_ctl);
+ printk(" INT_REG = %8x\n", iodpp->int_reg);
+ printk(" INT_MASK0 = %8x\n", iodpp->int_mask0);
+ printk(" INT_MASK1 = %8x\n", iodpp->int_mask1);
+ printk(" MC_ERR0 = %8x\n", iodpp->mc_err0);
+ printk(" MC_ERR1 = %8x\n", iodpp->mc_err1);
+ printk(" CAP_ERR = %8x\n", iodpp->cap_err);
+ printk(" PCI_ERR1 = %8x\n", iodpp->pci_err1);
+ printk(" MDPA_STAT = %8x\n", iodpp->mdpa_stat);
+ printk(" MDPA_SYN = %8x\n", iodpp->mdpa_syn);
+ printk(" MDPB_STAT = %8x\n", iodpp->mdpb_stat);
+ printk(" MDPB_SYN = %8x\n", iodpp->mdpb_syn);
+ }
+}
+
void
mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
@@ -594,6 +659,8 @@ mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
mb();
process_mcheck_info(vector, la_ptr, regs, "MCPCIA", expected != 0);
- if (!expected && vector != 0x620 && vector != 0x630)
+ if (!expected && vector != 0x620 && vector != 0x630) {
mcpcia_print_uncorrectable(mchk_logout);
+ mcpcia_print_system_area(la_ptr);
+ }
}
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
new file mode 100644
index 000000000..65bcc8651
--- /dev/null
+++ b/arch/alpha/kernel/core_titan.c
@@ -0,0 +1,486 @@
+/*
+ * linux/arch/alpha/kernel/core_titan.c
+ *
+ * Code common to all TITAN 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/smp.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_titan.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+#include "pci_impl.h"
+
+int TITAN_bootcpu;
+unsigned TITAN_agp = 0;
+
+static struct
+{
+ unsigned long wsba[4];
+ unsigned long wsm[4];
+ unsigned long tba[4];
+} saved_pachip_port[4];
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#define DEBUG_MCHECK 0 /* 0 = minimum, 1 = debug, 2 = dump+dump */
+#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.
+ *
+ * Note that all config space accesses use Type 1 address format.
+ *
+ * Note also that type 1 is determined by non-zero bus number.
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * 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)
+{
+ struct pci_controler *hose = dev->sysdata;
+ 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));
+
+ if (hose->first_busno == dev->bus->number)
+ bus = 0;
+ *type1 = (bus != 0);
+
+ addr = (bus << 16) | (device_fn << 8) | where;
+ addr |= hose->config_space_base;
+
+ *pci_addr = addr;
+ DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+static int
+titan_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
+titan_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
+titan_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
+titan_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
+titan_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
+titan_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 titan_pci_ops =
+{
+ read_byte: titan_read_config_byte,
+ read_word: titan_read_config_word,
+ read_dword: titan_read_config_dword,
+ write_byte: titan_write_config_byte,
+ write_word: titan_write_config_word,
+ write_dword: titan_write_config_dword
+};
+
+
+void
+titan_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+ titan_pachip *pachip =
+ (hose->index & 1) ? TITAN_pachip1 : TITAN_pachip0;
+ titan_pachip_port *port;
+ volatile unsigned long *csr;
+ unsigned long value;
+
+ /* Get the right hose */
+ port = &pachip->g_port;
+ if (hose->index & 2)
+ port = &pachip->a_port;
+
+ /* We can invalidate up to 8 tlb entries in a go. The flush
+ matches against <31:16> in the pci address. */
+ csr = &port->port_specific.g.gtlbia.csr;
+ if (((start ^ end) & 0xffff0000) == 0)
+ csr = &port->port_specific.g.gtlbiv.csr;
+
+ /* For TBIA, it doesn't matter what value we write. For TBI,
+ it's the shifted tag bits. */
+ value = (start & 0xffff0000) >> 12;
+
+ wmb();
+ *csr = value;
+ mb();
+ *csr;
+}
+
+#define FN __FUNCTION__
+
+static int __init
+titan_query_agp(titan_pachip_port *port)
+{
+ union TPAchipPCTL pctl;
+
+ /* set up APCTL */
+ pctl.pctl_q_whole = port->pctl.csr;
+
+ return pctl.pctl_r_bits.apctl_v_agp_present;
+
+}
+static void __init
+titan_init_agp(titan_pachip_port *port, struct pci_controler *hose)
+{
+ union TPAchipPCTL pctl;
+
+ if (!titan_query_agp(port))
+ return;
+
+ printk("AGP present on hose %d\n", hose->index);
+
+ /* get APCTL */
+ pctl.pctl_q_whole = port->pctl.csr;
+
+
+ pctl.pctl_r_bits.apctl_v_agp_en = 1; /* enable AGP */
+ pctl.pctl_r_bits.apctl_v_agp_lp_rd = 0;
+ pctl.pctl_r_bits.apctl_v_agp_hp_rd = 0;
+
+ port->pctl.csr = pctl.pctl_q_whole;
+
+ TITAN_agp |= 1 << hose->index;
+
+#ifdef CONFIG_VGA_HOSE
+ /* is a graphics card on the AGP? (always device 5) */
+ if (hose != NULL &&
+ __kernel_ldwu(*(vusp)(hose->config_space_base + 0x280a)) ==
+ PCI_CLASS_DISPLAY_VGA)
+ set_vga_hose(hose);
+#endif
+}
+
+static void __init
+titan_init_one_pachip_port(titan_pachip_port *port, int index)
+{
+ struct pci_controler *hose;
+
+ hose = alloc_pci_controler();
+ if (index == 0)
+ pci_isa_hose = hose;
+ hose->io_space = alloc_resource();
+ hose->mem_space = alloc_resource();
+
+ hose->config_space_base = TITAN_CONF(index);
+ hose->index = index;
+
+ hose->io_space->start = TITAN_IO(index) - TITAN_IO_BIAS;
+ hose->io_space->end = hose->io_space->start + TITAN_IO_SPACE - 1;
+ hose->io_space->name = pci_io_names[index];
+ hose->io_space->flags = IORESOURCE_IO;
+
+ hose->mem_space->start = TITAN_MEM(index) - TITAN_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);
+
+ /* It's safe to call this for both G-Ports and A-Ports */
+ titan_init_agp(port, hose);
+
+ /*
+ * Save the existing PCI window translations. SRM will
+ * need them when we go to reboot.
+ */
+ saved_pachip_port[index].wsba[0] = port->wsba[0].csr;
+ saved_pachip_port[index].wsm[0] = port->wsm[0].csr;
+ saved_pachip_port[index].tba[0] = port->tba[0].csr;
+
+ saved_pachip_port[index].wsba[1] = port->wsba[1].csr;
+ saved_pachip_port[index].wsm[1] = port->wsm[1].csr;
+ saved_pachip_port[index].tba[1] = port->tba[1].csr;
+
+ saved_pachip_port[index].wsba[2] = port->wsba[2].csr;
+ saved_pachip_port[index].wsm[2] = port->wsm[2].csr;
+ saved_pachip_port[index].tba[2] = port->tba[2].csr;
+
+ saved_pachip_port[index].wsba[3] = port->wsba[3].csr;
+ saved_pachip_port[index].wsm[3] = port->wsm[3].csr;
+ saved_pachip_port[index].tba[3] = port->tba[3].csr;
+
+ /*
+ * Set up the PCI to main memory translation windows.
+ *
+ * Note: Window 3 on Titan is Scatter-Gather ONLY
+ *
+ * Window 0 is scatter-gather 8MB at 8MB (for isa)
+ * Window 1 is direct access 1GB at 1GB
+ * Window 2 is direct access 1GB at 2GB
+ * Window 3 is scatter-gather 128MB at 3GB
+ * ??? We ought to scale window 3 memory.
+ *
+ * We must actually use 2 windows to direct-map the 2GB space,
+ * because of an idiot-syncrasy of the CYPRESS chip. It may
+ * respond to a PCI bus address in the last 1MB of the 4GB
+ * address range.
+ */
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
+ hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0);
+ __direct_map_base = 0x40000000;
+ __direct_map_size = 0x80000000;
+
+ port->wsba[0].csr = hose->sg_isa->dma_base | 3;
+ port->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000;
+ port->tba[0].csr = virt_to_phys(hose->sg_isa->ptes);
+
+ port->wsba[1].csr = 0x40000000 | 1;
+ port->wsm[1].csr = (0x40000000 - 1) & 0xfff00000;
+ port->tba[1].csr = 0;
+
+ port->wsba[2].csr = 0x80000000 | 1;
+ port->wsm[2].csr = (0x40000000 - 1) & 0xfff00000;
+ port->tba[2].csr = 0x40000000;
+
+ port->wsba[3].csr = hose->sg_pci->dma_base | 3;
+ port->wsm[3].csr = (hose->sg_pci->size - 1) & 0xfff00000;
+ port->tba[3].csr = virt_to_phys(hose->sg_pci->ptes);
+
+ titan_pci_tbi(hose, 0, -1);
+}
+
+static void __init
+titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
+{
+ int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
+
+ /* Init the ports in hose order... */
+ titan_init_one_pachip_port(&pachip0->g_port, 0); /* hose 0 */
+ if (pchip1_present)
+ titan_init_one_pachip_port(&pachip1->g_port, 1);/* hose 1 */
+ titan_init_one_pachip_port(&pachip0->a_port, 2); /* hose 2 */
+ if (pchip1_present)
+ titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
+}
+
+void __init
+titan_init_arch(void)
+{
+#if 0
+ printk("%s: titan_init_arch()\n", FN);
+ printk("%s: CChip registers:\n", FN);
+ printk("%s: CSR_CSC 0x%lx\n", FN, TITAN_cchip->csc.csr);
+ printk("%s: CSR_MTR 0x%lx\n", FN, TITAN_cchip->mtr.csr);
+ printk("%s: CSR_MISC 0x%lx\n", FN, TITAN_cchip->misc.csr);
+ printk("%s: CSR_DIM0 0x%lx\n", FN, TITAN_cchip->dim0.csr);
+ printk("%s: CSR_DIM1 0x%lx\n", FN, TITAN_cchip->dim1.csr);
+ printk("%s: CSR_DIR0 0x%lx\n", FN, TITAN_cchip->dir0.csr);
+ printk("%s: CSR_DIR1 0x%lx\n", FN, TITAN_cchip->dir1.csr);
+ printk("%s: CSR_DRIR 0x%lx\n", FN, TITAN_cchip->drir.csr);
+
+ printk("%s: DChip registers:\n", FN);
+ printk("%s: CSR_DSC 0x%lx\n", FN, TITAN_dchip->dsc.csr);
+ printk("%s: CSR_STR 0x%lx\n", FN, TITAN_dchip->str.csr);
+ printk("%s: CSR_DREV 0x%lx\n", FN, TITAN_dchip->drev.csr);
+#endif
+
+ TITAN_bootcpu = __hard_smp_processor_id();
+
+ /* With multiple PCI busses, we play with I/O as physical addrs. */
+ ioport_resource.end = ~0UL;
+ iomem_resource.end = ~0UL;
+
+ /* Init the PA chip(s) */
+ titan_init_pachips(TITAN_pachip0, TITAN_pachip1);
+}
+
+static void
+titan_kill_one_pachip_port(titan_pachip_port *port, int index)
+{
+ port->wsba[0].csr = saved_pachip_port[index].wsba[0];
+ port->wsm[0].csr = saved_pachip_port[index].wsm[0];
+ port->tba[0].csr = saved_pachip_port[index].tba[0];
+
+ port->wsba[1].csr = saved_pachip_port[index].wsba[1];
+ port->wsm[1].csr = saved_pachip_port[index].wsm[1];
+ port->tba[1].csr = saved_pachip_port[index].tba[1];
+
+ port->wsba[2].csr = saved_pachip_port[index].wsba[2];
+ port->wsm[2].csr = saved_pachip_port[index].wsm[2];
+ port->tba[2].csr = saved_pachip_port[index].tba[2];
+
+ port->wsba[3].csr = saved_pachip_port[index].wsba[3];
+ port->wsm[3].csr = saved_pachip_port[index].wsm[3];
+ port->tba[3].csr = saved_pachip_port[index].tba[3];
+}
+
+static void
+titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
+{
+ int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
+
+ if (pchip1_present) {
+ titan_kill_one_pachip_port(&pachip0->g_port, 1);
+ titan_kill_one_pachip_port(&pachip0->a_port, 3);
+ }
+ titan_kill_one_pachip_port(&pachip0->g_port, 0);
+ titan_kill_one_pachip_port(&pachip0->a_port, 2);
+}
+
+void
+titan_kill_arch(int mode)
+{
+ titan_kill_pachips(TITAN_pachip0, TITAN_pachip1);
+}
+
+static inline void
+titan_pci_clr_err_1(titan_pachip *pachip)
+{
+ unsigned int jd;
+
+ jd = pachip->g_port.port_specific.g.gperror.csr;
+ pachip->g_port.port_specific.g.gperror.csr = jd;
+ mb();
+ pachip->g_port.port_specific.g.gperror.csr;
+}
+
+static inline void
+titan_pci_clr_err(void)
+{
+ titan_pci_clr_err_1(TITAN_pachip0);
+
+ if (TITAN_cchip->csc.csr & 1L<<14)
+ titan_pci_clr_err_1(TITAN_pachip1);
+}
+
+void
+titan_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ /* clear error before any reporting. */
+ mb();
+ draina();
+ titan_pci_clr_err();
+ wrmces(0x7);
+ mb();
+
+ process_mcheck_info(vector, la_ptr, regs, "TITAN",
+ mcheck_expected(smp_processor_id()));
+}
+
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index 5e3943fec..45ff9bb12 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -344,11 +344,13 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
/*
* Set up the PCI to main memory translation windows.
*
+ * Note: Window 3 is scatter-gather only
+ *
* Window 0 is scatter-gather 8MB at 8MB (for isa)
- * Window 1 is scatter-gather 128MB at 3GB
- * Window 2 is direct access 1GB at 1GB
- * Window 3 is direct access 1GB at 2GB
- * ??? We ought to scale window 1 memory.
+ * Window 1 is direct access 1GB at 1GB
+ * Window 2 is direct access 1GB at 2GB
+ * Window 3 is scatter-gather 128MB at 3GB
+ * ??? We ought to scale window 3 memory.
*
* We must actually use 2 windows to direct-map the 2GB space,
* because of an idiot-syncrasy of the CYPRESS chip. It may
@@ -364,17 +366,17 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
pchip->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000;
pchip->tba[0].csr = virt_to_phys(hose->sg_isa->ptes);
- pchip->wsba[1].csr = hose->sg_pci->dma_base | 3;
- pchip->wsm[1].csr = (hose->sg_pci->size - 1) & 0xfff00000;
- pchip->tba[1].csr = virt_to_phys(hose->sg_pci->ptes);
+ pchip->wsba[1].csr = 0x40000000 | 1;
+ pchip->wsm[1].csr = (0x40000000 - 1) & 0xfff00000;
+ pchip->tba[1].csr = 0;
- pchip->wsba[2].csr = 0x40000000 | 1;
+ pchip->wsba[2].csr = 0x80000000 | 1;
pchip->wsm[2].csr = (0x40000000 - 1) & 0xfff00000;
- pchip->tba[2].csr = 0;
+ pchip->tba[2].csr = 0x40000000;
- pchip->wsba[3].csr = 0x80000000 | 1;
- pchip->wsm[3].csr = (0x40000000 - 1) & 0xfff00000;
- pchip->tba[3].csr = 0x40000000;
+ pchip->wsba[3].csr = hose->sg_pci->dma_base | 3;
+ pchip->wsm[3].csr = (hose->sg_pci->size - 1) & 0xfff00000;
+ pchip->tba[3].csr = virt_to_phys(hose->sg_pci->ptes);
tsunami_pci_tbi(hose, 0, -1);
}
diff --git a/arch/alpha/kernel/core_wildfire.c b/arch/alpha/kernel/core_wildfire.c
new file mode 100644
index 000000000..9b4f28c10
--- /dev/null
+++ b/arch/alpha/kernel/core_wildfire.c
@@ -0,0 +1,668 @@
+/*
+ * linux/arch/alpha/kernel/core_wildfire.c
+ *
+ * Wildfire support.
+ *
+ * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
+ */
+
+#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/smp.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_wildfire.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+#include "pci_impl.h"
+
+#define DEBUG_MCHECK 0 /* 0 = minimal, 1 = debug, 2 = debug+dump. */
+#define DEBUG_CONFIG 0
+#define DEBUG_DUMP_REGS 0
+#define DEBUG_DUMP_CONFIG 1
+
+#if DEBUG_CONFIG
+# define DBG_CFG(args) printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+#if DEBUG_DUMP_REGS
+static void wildfire_dump_pci_regs(int qbbno, int hoseno);
+static void wildfire_dump_pca_regs(int qbbno, int pcano);
+static void wildfire_dump_qsa_regs(int qbbno);
+static void wildfire_dump_qsd_regs(int qbbno);
+static void wildfire_dump_iop_regs(int qbbno);
+static void wildfire_dump_gp_regs(int qbbno);
+#endif
+#if DEBUG_DUMP_CONFIG
+static void wildfire_dump_hardware_config(void);
+#endif
+
+unsigned char wildfire_hard_qbb_map[WILDFIRE_MAX_QBB];
+unsigned char wildfire_soft_qbb_map[WILDFIRE_MAX_QBB];
+#define QBB_MAP_EMPTY 0xff
+
+unsigned long wildfire_hard_qbb_mask;
+unsigned long wildfire_soft_qbb_mask;
+unsigned long wildfire_gp_mask;
+unsigned long wildfire_hs_mask;
+unsigned long wildfire_iop_mask;
+unsigned long wildfire_ior_mask;
+unsigned long wildfire_pca_mask;
+unsigned long wildfire_cpu_mask;
+unsigned long wildfire_mem_mask;
+
+void __init
+wildfire_init_hose(int qbbno, int hoseno)
+{
+ struct pci_controler *hose;
+ wildfire_pci *pci;
+
+ hose = alloc_pci_controler();
+ hose->io_space = alloc_resource();
+ hose->mem_space = alloc_resource();
+
+ /* This is for userland consumption. */
+ hose->sparse_mem_base = 0;
+ hose->sparse_io_base = 0;
+ hose->dense_mem_base = WILDFIRE_MEM(qbbno, hoseno);
+ hose->dense_io_base = WILDFIRE_IO(qbbno, hoseno);
+
+ hose->config_space_base = WILDFIRE_CONF(qbbno, hoseno);
+ hose->index = (qbbno << 3) + hoseno;
+
+ hose->io_space->start = WILDFIRE_IO(qbbno, hoseno) - WILDFIRE_IO_BIAS;
+ hose->io_space->end = hose->io_space->start + WILDFIRE_IO_SPACE - 1;
+ hose->io_space->name = pci_io_names[hoseno];
+ hose->io_space->flags = IORESOURCE_IO;
+
+ hose->mem_space->start = WILDFIRE_MEM(qbbno, hoseno)-WILDFIRE_MEM_BIAS;
+ hose->mem_space->end = hose->mem_space->start + 0xffffffff;
+ hose->mem_space->name = pci_mem_names[hoseno];
+ hose->mem_space->flags = IORESOURCE_MEM;
+
+ if (request_resource(&ioport_resource, hose->io_space) < 0)
+ printk(KERN_ERR "Failed to request IO on qbb %d hose %d\n",
+ qbbno, hoseno);
+ if (request_resource(&iomem_resource, hose->mem_space) < 0)
+ printk(KERN_ERR "Failed to request MEM on qbb %d hose %d\n",
+ qbbno, hoseno);
+
+#if DEBUG_DUMP_REGS
+ wildfire_dump_pci_regs(qbbno, hoseno);
+#endif
+
+ /*
+ * Set up the PCI to main memory translation windows.
+ *
+ * Note: Window 3 is scatter-gather only
+ *
+ * Window 0 is scatter-gather 8MB at 8MB (for isa)
+ * Window 1 is direct access 1GB at 1GB
+ * Window 2 is direct access 1GB at 2GB
+ * Window 3 is scatter-gather 128MB at 3GB
+ * ??? We ought to scale window 3 memory.
+ *
+ */
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
+ hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0);
+
+ pci = WILDFIRE_pci(qbbno, hoseno);
+
+ pci->pci_window[0].wbase.csr = hose->sg_isa->dma_base | 3;
+ pci->pci_window[0].wmask.csr = (hose->sg_isa->size - 1) & 0xfff00000;
+ pci->pci_window[0].tbase.csr = virt_to_phys(hose->sg_isa->ptes);
+
+ pci->pci_window[1].wbase.csr = 0x40000000 | 1;
+ pci->pci_window[1].wmask.csr = (0x40000000 -1) & 0xfff00000;
+ pci->pci_window[1].tbase.csr = 0;
+
+ pci->pci_window[2].wbase.csr = 0x80000000 | 1;
+ pci->pci_window[2].wmask.csr = (0x40000000 -1) & 0xfff00000;
+ pci->pci_window[2].tbase.csr = 0x40000000;
+
+ pci->pci_window[3].wbase.csr = hose->sg_pci->dma_base | 3;
+ pci->pci_window[3].wmask.csr = (hose->sg_pci->size - 1) & 0xfff00000;
+ pci->pci_window[3].tbase.csr = virt_to_phys(hose->sg_pci->ptes);
+
+ wildfire_pci_tbi(hose, 0, 0); /* Flush TLB at the end. */
+}
+
+void __init
+wildfire_init_pca(int qbbno, int pcano)
+{
+
+ /* Test for PCA existence first. */
+ if (!WILDFIRE_PCA_EXISTS(qbbno, pcano))
+ return;
+
+#if DEBUG_DUMP_REGS
+ wildfire_dump_pca_regs(qbbno, pcano);
+#endif
+
+ /* Do both hoses of the PCA. */
+ wildfire_init_hose(qbbno, (pcano << 1) + 0);
+ wildfire_init_hose(qbbno, (pcano << 1) + 1);
+}
+
+void __init
+wildfire_init_qbb(int qbbno)
+{
+ int pcano;
+
+ /* Test for QBB existence first. */
+ if (!WILDFIRE_QBB_EXISTS(qbbno))
+ return;
+
+#if DEBUG_DUMP_REGS
+ wildfire_dump_qsa_regs(qbbno);
+ wildfire_dump_qsd_regs(qbbno);
+ wildfire_dump_iop_regs(qbbno);
+ wildfire_dump_gp_regs(qbbno);
+#endif
+
+ /* Init all PCAs here. */
+ for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
+ wildfire_init_pca(qbbno, pcano);
+ }
+}
+
+void __init
+wildfire_hardware_probe(void)
+{
+ unsigned long temp;
+ unsigned int hard_qbb, soft_qbb;
+ wildfire_fast_qsd *fast = WILDFIRE_fast_qsd();
+ wildfire_qsd *qsd;
+ wildfire_qsa *qsa;
+ wildfire_iop *iop;
+ wildfire_gp *gp;
+ wildfire_ne *ne;
+ wildfire_fe *fe;
+ int i;
+
+ temp = fast->qsd_whami.csr;
+#if 0
+ printk(KERN_ERR "fast QSD_WHAMI at base %p is 0x%lx\n", fast, temp);
+#endif
+
+ hard_qbb = (temp >> 8) & 7;
+ soft_qbb = (temp >> 4) & 7;
+
+ /* Init the HW configuration variables. */
+ wildfire_hard_qbb_mask = (1 << hard_qbb);
+ wildfire_soft_qbb_mask = (1 << soft_qbb);
+
+ wildfire_gp_mask = 0;
+ wildfire_hs_mask = 0;
+ wildfire_iop_mask = 0;
+ wildfire_ior_mask = 0;
+ wildfire_pca_mask = 0;
+
+ wildfire_cpu_mask = 0;
+ wildfire_mem_mask = 0;
+
+ memset(wildfire_hard_qbb_map, QBB_MAP_EMPTY, WILDFIRE_MAX_QBB);
+ memset(wildfire_soft_qbb_map, QBB_MAP_EMPTY, WILDFIRE_MAX_QBB);
+
+ /* First, determine which QBBs are present. */
+ qsa = WILDFIRE_qsa(soft_qbb);
+
+ temp = qsa->qsa_qbb_id.csr;
+#if 0
+ printk(KERN_ERR "QSA_QBB_ID at base %p is 0x%lx\n", qsa, temp);
+#endif
+
+ if (temp & 0x40) /* Is there an HS? */
+ wildfire_hs_mask = 1;
+
+ if (temp & 0x20) { /* Is there a GP? */
+ gp = WILDFIRE_gp(soft_qbb);
+ temp = 0;
+ for (i = 0; i < 4; i++) {
+ temp |= gp->gpa_qbb_map[i].csr << (i * 8);
+#if 0
+ printk(KERN_ERR "GPA_QBB_MAP[%d] at base %p is 0x%lx\n",
+ i, gp, temp);
+#endif
+ }
+
+ for (hard_qbb = 0; hard_qbb < WILDFIRE_MAX_QBB; hard_qbb++) {
+ if (temp & 8) { /* Is there a QBB? */
+ soft_qbb = temp & 7;
+ wildfire_hard_qbb_mask |= (1 << hard_qbb);
+ wildfire_soft_qbb_mask |= (1 << soft_qbb);
+ }
+ temp >>= 4;
+ }
+ wildfire_gp_mask = wildfire_soft_qbb_mask;
+ }
+
+ /* Next determine each QBBs resources. */
+ for (soft_qbb = 0; soft_qbb < WILDFIRE_MAX_QBB; soft_qbb++) {
+ if (WILDFIRE_QBB_EXISTS(soft_qbb)) {
+ qsd = WILDFIRE_qsd(soft_qbb);
+ temp = qsd->qsd_whami.csr;
+#if 0
+ printk(KERN_ERR "QSD_WHAMI at base %p is 0x%lx\n", qsd, temp);
+#endif
+ hard_qbb = (temp >> 8) & 7;
+ wildfire_hard_qbb_map[hard_qbb] = soft_qbb;
+ wildfire_soft_qbb_map[soft_qbb] = hard_qbb;
+
+ qsa = WILDFIRE_qsa(soft_qbb);
+ temp = qsa->qsa_qbb_pop[0].csr;
+#if 0
+ printk(KERN_ERR "QSA_QBB_POP_0 at base %p is 0x%lx\n", qsa, temp);
+#endif
+ wildfire_cpu_mask |= ((temp >> 0) & 0xf) << (soft_qbb << 2);
+ wildfire_mem_mask |= ((temp >> 4) & 0xf) << (soft_qbb << 2);
+
+ temp = qsa->qsa_qbb_pop[1].csr;
+#if 0
+ printk(KERN_ERR "QSA_QBB_POP_1 at base %p is 0x%lx\n", qsa, temp);
+#endif
+ wildfire_iop_mask |= (1 << soft_qbb);
+ wildfire_ior_mask |= ((temp >> 4) & 0xf) << (soft_qbb << 2);
+
+ temp = qsa->qsa_qbb_id.csr;
+#if 0
+ printk(KERN_ERR "QSA_QBB_ID at %p is 0x%lx\n", qsa, temp);
+#endif
+ if (temp & 0x20)
+ wildfire_gp_mask |= (1 << soft_qbb);
+
+ /* Probe for PCA existence here. */
+ for (i = 0; i < WILDFIRE_PCA_PER_QBB; i++) {
+ iop = WILDFIRE_iop(soft_qbb);
+ ne = WILDFIRE_ne(soft_qbb, i);
+ fe = WILDFIRE_fe(soft_qbb, i);
+
+ if ((iop->iop_hose[i].init.csr & 1) == 1 &&
+ ((ne->ne_what_am_i.csr & 0xf00000300) == 0x100000300) &&
+ ((fe->fe_what_am_i.csr & 0xf00000300) == 0x100000200))
+ {
+ wildfire_pca_mask |= 1 << ((soft_qbb << 2) + i);
+ }
+ }
+
+ }
+ }
+#if DEBUG_DUMP_CONFIG
+ wildfire_dump_hardware_config();
+#endif
+}
+
+void __init
+wildfire_init_arch(void)
+{
+ int qbbno;
+
+ /* With multiple PCI buses, we play with I/O as physical addrs. */
+ ioport_resource.end = ~0UL;
+ iomem_resource.end = ~0UL;
+
+
+ /* Probe the hardware for info about configuration. */
+ wildfire_hardware_probe();
+
+ /* Now init all the found QBBs. */
+ for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
+ wildfire_init_qbb(qbbno);
+ }
+
+ /* Normal direct PCI DMA mapping. */
+ __direct_map_base = 0x40000000UL;
+ __direct_map_size = 0x80000000UL;
+}
+
+void
+wildfire_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ mb();
+ mb(); /* magic */
+ draina();
+ /* FIXME: clear pci errors */
+ wrmces(0x7);
+ mb();
+
+ process_mcheck_info(vector, la_ptr, regs, "WILDFIRE",
+ mcheck_expected(smp_processor_id()));
+}
+
+void
+wildfire_kill_arch(int mode)
+{
+}
+
+void
+wildfire_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+ int qbbno = hose->index >> 3;
+ int hoseno = hose->index & 7;
+ wildfire_pci *pci = WILDFIRE_pci(qbbno, hoseno);
+
+ mb();
+ pci->pci_flush_tlb.csr; /* reading does the trick */
+}
+
+static int
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ struct pci_controler *hose = dev->sysdata;
+ 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));
+
+ if (hose->first_busno == dev->bus->number)
+ bus = 0;
+ *type1 = (bus != 0);
+
+ addr = (bus << 16) | (device_fn << 8) | where;
+ addr |= hose->config_space_base;
+
+ *pci_addr = addr;
+ DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+static int
+wildfire_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
+wildfire_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
+wildfire_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
+wildfire_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
+wildfire_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
+wildfire_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 wildfire_pci_ops =
+{
+ read_byte: wildfire_read_config_byte,
+ read_word: wildfire_read_config_word,
+ read_dword: wildfire_read_config_dword,
+ write_byte: wildfire_write_config_byte,
+ write_word: wildfire_write_config_word,
+ write_dword: wildfire_write_config_dword
+};
+
+#if DEBUG_DUMP_REGS
+
+static void __init
+wildfire_dump_pci_regs(int qbbno, int hoseno)
+{
+ wildfire_pci *pci = WILDFIRE_pci(qbbno, hoseno);
+ int i;
+
+ printk(KERN_ERR "PCI registers for QBB %d hose %d (%p)\n",
+ qbbno, hoseno, pci);
+
+ printk(KERN_ERR " PCI_IO_ADDR_EXT: 0x%16lx\n",
+ pci->pci_io_addr_ext.csr);
+ printk(KERN_ERR " PCI_CTRL: 0x%16lx\n", pci->pci_ctrl.csr);
+ printk(KERN_ERR " PCI_ERR_SUM: 0x%16lx\n", pci->pci_err_sum.csr);
+ printk(KERN_ERR " PCI_ERR_ADDR: 0x%16lx\n", pci->pci_err_addr.csr);
+ printk(KERN_ERR " PCI_STALL_CNT: 0x%16lx\n", pci->pci_stall_cnt.csr);
+ printk(KERN_ERR " PCI_PEND_INT: 0x%16lx\n", pci->pci_pend_int.csr);
+ printk(KERN_ERR " PCI_SENT_INT: 0x%16lx\n", pci->pci_sent_int.csr);
+
+ printk(KERN_ERR " DMA window registers for QBB %d hose %d (%p)\n",
+ qbbno, hoseno, pci);
+ for (i = 0; i < 4; i++) {
+ printk(KERN_ERR " window %d: 0x%16lx 0x%16lx 0x%16lx\n", i,
+ pci->pci_window[i].wbase.csr,
+ pci->pci_window[i].wmask.csr,
+ pci->pci_window[i].tbase.csr);
+ }
+ printk(KERN_ERR "\n");
+}
+
+static void __init
+wildfire_dump_pca_regs(int qbbno, int pcano)
+{
+ wildfire_pca *pca = WILDFIRE_pca(qbbno, pcano);
+ int i;
+
+ printk(KERN_ERR "PCA registers for QBB %d PCA %d (%p)\n",
+ qbbno, pcano, pca);
+
+ printk(KERN_ERR " PCA_WHAT_AM_I: 0x%16lx\n", pca->pca_what_am_i.csr);
+ printk(KERN_ERR " PCA_ERR_SUM: 0x%16lx\n", pca->pca_err_sum.csr);
+ printk(KERN_ERR " PCA_PEND_INT: 0x%16lx\n", pca->pca_pend_int.csr);
+ printk(KERN_ERR " PCA_SENT_INT: 0x%16lx\n", pca->pca_sent_int.csr);
+ printk(KERN_ERR " PCA_STDIO_EL: 0x%16lx\n",
+ pca->pca_stdio_edge_level.csr);
+
+ printk(KERN_ERR " PCA target registers for QBB %d PCA %d (%p)\n",
+ qbbno, pcano, pca);
+ for (i = 0; i < 4; i++) {
+ printk(KERN_ERR " target %d: 0x%16lx 0x%16lx\n", i,
+ pca->pca_int[i].target.csr,
+ pca->pca_int[i].enable.csr);
+ }
+
+ printk(KERN_ERR "\n");
+}
+
+static void __init
+wildfire_dump_qsa_regs(int qbbno)
+{
+ wildfire_qsa *qsa = WILDFIRE_qsa(qbbno);
+ int i;
+
+ printk(KERN_ERR "QSA registers for QBB %d (%p)\n", qbbno, qsa);
+
+ printk(KERN_ERR " QSA_QBB_ID: 0x%16lx\n", qsa->qsa_qbb_id.csr);
+ printk(KERN_ERR " QSA_PORT_ENA: 0x%16lx\n", qsa->qsa_port_ena.csr);
+ printk(KERN_ERR " QSA_REF_INT: 0x%16lx\n", qsa->qsa_ref_int.csr);
+
+ for (i = 0; i < 5; i++)
+ printk(KERN_ERR " QSA_CONFIG_%d: 0x%16lx\n",
+ i, qsa->qsa_config[i].csr);
+
+ for (i = 0; i < 2; i++)
+ printk(KERN_ERR " QSA_QBB_POP_%d: 0x%16lx\n",
+ i, qsa->qsa_qbb_pop[0].csr);
+
+ printk(KERN_ERR "\n");
+}
+
+static void __init
+wildfire_dump_qsd_regs(int qbbno)
+{
+ wildfire_qsd *qsd = WILDFIRE_qsd(qbbno);
+
+ printk(KERN_ERR "QSD registers for QBB %d (%p)\n", qbbno, qsd);
+
+ printk(KERN_ERR " QSD_WHAMI: 0x%16lx\n", qsd->qsd_whami.csr);
+ printk(KERN_ERR " QSD_REV: 0x%16lx\n", qsd->qsd_rev.csr);
+ printk(KERN_ERR " QSD_PORT_PRESENT: 0x%16lx\n",
+ qsd->qsd_port_present.csr);
+ printk(KERN_ERR " QSD_PORT_ACTUVE: 0x%16lx\n",
+ qsd->qsd_port_active.csr);
+ printk(KERN_ERR " QSD_FAULT_ENA: 0x%16lx\n",
+ qsd->qsd_fault_ena.csr);
+ printk(KERN_ERR " QSD_CPU_INT_ENA: 0x%16lx\n",
+ qsd->qsd_cpu_int_ena.csr);
+ printk(KERN_ERR " QSD_MEM_CONFIG: 0x%16lx\n",
+ qsd->qsd_mem_config.csr);
+ printk(KERN_ERR " QSD_ERR_SUM: 0x%16lx\n",
+ qsd->qsd_err_sum.csr);
+
+ printk(KERN_ERR "\n");
+}
+
+static void __init
+wildfire_dump_iop_regs(int qbbno)
+{
+ wildfire_iop *iop = WILDFIRE_iop(qbbno);
+ int i;
+
+ printk(KERN_ERR "IOP registers for QBB %d (%p)\n", qbbno, iop);
+
+ printk(KERN_ERR " IOA_CONFIG: 0x%16lx\n", iop->ioa_config.csr);
+ printk(KERN_ERR " IOD_CONFIG: 0x%16lx\n", iop->iod_config.csr);
+ printk(KERN_ERR " IOP_SWITCH_CREDITS: 0x%16lx\n",
+ iop->iop_switch_credits.csr);
+ printk(KERN_ERR " IOP_HOSE_CREDITS: 0x%16lx\n",
+ iop->iop_hose_credits.csr);
+
+ for (i = 0; i < 4; i++)
+ printk(KERN_ERR " IOP_HOSE_%d_INIT: 0x%16lx\n",
+ i, iop->iop_hose[i].init.csr);
+ for (i = 0; i < 4; i++)
+ printk(KERN_ERR " IOP_DEV_INT_TARGET_%d: 0x%16lx\n",
+ i, iop->iop_dev_int[i].target.csr);
+
+ printk(KERN_ERR "\n");
+}
+
+static void __init
+wildfire_dump_gp_regs(int qbbno)
+{
+ wildfire_gp *gp = WILDFIRE_gp(qbbno);
+ int i;
+
+ printk(KERN_ERR "GP registers for QBB %d (%p)\n", qbbno, gp);
+ for (i = 0; i < 4; i++)
+ printk(KERN_ERR " GPA_QBB_MAP_%d: 0x%16lx\n",
+ i, gp->gpa_qbb_map[i].csr);
+
+ printk(KERN_ERR " GPA_MEM_POP_MAP: 0x%16lx\n",
+ gp->gpa_mem_pop_map.csr);
+ printk(KERN_ERR " GPA_SCRATCH: 0x%16lx\n", gp->gpa_scratch.csr);
+ printk(KERN_ERR " GPA_DIAG: 0x%16lx\n", gp->gpa_diag.csr);
+ printk(KERN_ERR " GPA_CONFIG_0: 0x%16lx\n", gp->gpa_config_0.csr);
+ printk(KERN_ERR " GPA_INIT_ID: 0x%16lx\n", gp->gpa_init_id.csr);
+ printk(KERN_ERR " GPA_CONFIG_2: 0x%16lx\n", gp->gpa_config_2.csr);
+
+ printk(KERN_ERR "\n");
+}
+#endif /* DUMP_REGS */
+
+#if DEBUG_DUMP_CONFIG
+static void __init
+wildfire_dump_hardware_config(void)
+{
+ int i;
+
+ printk(KERN_ERR "Probed Hardware Configuration\n");
+
+ printk(KERN_ERR " hard_qbb_mask: 0x%16lx\n", wildfire_hard_qbb_mask);
+ printk(KERN_ERR " soft_qbb_mask: 0x%16lx\n", wildfire_soft_qbb_mask);
+
+ printk(KERN_ERR " gp_mask: 0x%16lx\n", wildfire_gp_mask);
+ printk(KERN_ERR " hs_mask: 0x%16lx\n", wildfire_hs_mask);
+ printk(KERN_ERR " iop_mask: 0x%16lx\n", wildfire_iop_mask);
+ printk(KERN_ERR " ior_mask: 0x%16lx\n", wildfire_ior_mask);
+ printk(KERN_ERR " pca_mask: 0x%16lx\n", wildfire_pca_mask);
+
+ printk(KERN_ERR " cpu_mask: 0x%16lx\n", wildfire_cpu_mask);
+ printk(KERN_ERR " mem_mask: 0x%16lx\n", wildfire_mem_mask);
+
+ printk(" hard_qbb_map: ");
+ for (i = 0; i < WILDFIRE_MAX_QBB; i++)
+ if (wildfire_hard_qbb_map[i] == QBB_MAP_EMPTY)
+ printk("--- ");
+ else
+ printk("%3d ", wildfire_hard_qbb_map[i]);
+ printk("\n");
+
+ printk(" soft_qbb_map: ");
+ for (i = 0; i < WILDFIRE_MAX_QBB; i++)
+ if (wildfire_soft_qbb_map[i] == QBB_MAP_EMPTY)
+ printk("--- ");
+ else
+ printk("%3d ", wildfire_soft_qbb_map[i]);
+ printk("\n");
+}
+#endif /* DUMP_CONFIG */
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 33d5eead1..6f73ff9f9 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -34,11 +34,12 @@
#define TASK_EXEC_DOMAIN 32
#define TASK_NEED_RESCHED 40
#define TASK_PROCESSOR 100
+#define TASK_PTRACE 104
/*
* task flags (must match include/linux/sched.h):
*/
-#define PF_PTRACED 0x00000010
+#define PT_PTRACED 0x00000001
#define CLONE_VM 0x00000100
@@ -557,10 +558,10 @@ entSys:
lda $5,sys_call_table
lda $27,sys_ni_syscall
cmpult $0,$4,$4
- ldq $3,TASK_FLAGS($8)
+ ldq $3,TASK_PTRACE($8)
stq $17,SP_OFF+32($30)
s8addq $0,$5,$5
- and $3,PF_PTRACED,$3
+ and $3,PT_PTRACED,$3
stq $18,SP_OFF+40($30)
bne $3,strace
beq $4,1f
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index e47fcd3ca..dc665fbfb 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -233,14 +233,14 @@ static unsigned long irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
static void
select_smp_affinity(int irq)
{
- static int last_cpu;
+ static int last_cpu = 0;
int cpu = last_cpu + 1;
if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
return;
while (((cpu_present_mask >> cpu) & 1) == 0)
- cpu = (cpu < NR_CPUS ? cpu + 1 : 0);
+ cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
last_cpu = cpu;
irq_affinity[irq] = 1UL << cpu;
@@ -520,8 +520,10 @@ get_irq_list(char *buf)
p += sprintf(p, " ");
for (i = 0; i < smp_num_cpus; i++)
p += sprintf(p, "CPU%d ", i);
+#ifdef DO_BROADCAST_INTS
for (i = 0; i < smp_num_cpus; i++)
p += sprintf(p, "TRY%d ", i);
+#endif
*p++ = '\n';
#endif
@@ -536,10 +538,12 @@ get_irq_list(char *buf)
for (j = 0; j < smp_num_cpus; j++)
p += sprintf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
+#ifdef DO_BROADCAST_INTS
for (j = 0; j < smp_num_cpus; j++)
p += sprintf(p, "%10lu ",
irq_attempt(cpu_logical_map(j), i));
#endif
+#endif
p += sprintf(p, " %14s", irq_desc[i].handler->typename);
p += sprintf(p, " %c%s",
(action->flags & SA_INTERRUPT)?'+':' ',
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index 774fcf8a6..ff1570406 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -105,8 +105,18 @@ common_init_isa_dma(void)
void __init
init_IRQ(void)
{
- alpha_mv.init_irq();
+ /* Uh, this really MUST come first, just in case
+ * the platform init_irq() causes interrupts/mchecks
+ * (as is the case with RAWHIDE, at least).
+ */
wrent(entInt, 0);
+
+ alpha_mv.init_irq();
+
+ /* If we had wanted SRM console printk echoing early, undo it now. */
+ if (alpha_using_srm && srmcons_output) {
+ unregister_srm_console();
+ }
}
/*
diff --git a/arch/alpha/kernel/irq_i8259.c b/arch/alpha/kernel/irq_i8259.c
index 79a1c4fb5..42029b33f 100644
--- a/arch/alpha/kernel/irq_i8259.c
+++ b/arch/alpha/kernel/irq_i8259.c
@@ -126,6 +126,8 @@ init_i8259a_irqs(void)
# define IACK_SC CIA_IACK_SC
#elif defined(CONFIG_ALPHA_PYXIS)
# define IACK_SC PYXIS_IACK_SC
+#elif defined(CONFIG_ALPHA_TITAN)
+# define IACK_SC TITAN_IACK_SC
#elif defined(CONFIG_ALPHA_TSUNAMI)
# define IACK_SC TSUNAMI_IACK_SC
#elif defined(CONFIG_ALPHA_POLARIS)
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index bc9c0d3de..454950c1b 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -9,12 +9,14 @@
#include <linux/config.h>
#include <asm/pgalloc.h>
-/* 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. ;-) */
+/* Whee. IRONGATE, POLARIS, TSUNAMI, TITAN, and WILDFIRE 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 IRONGATE_HAE_ADDRESS (&alpha_mv.hae_cache)
#define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache)
#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
+#define TITAN_HAE_ADDRESS (&alpha_mv.hae_cache)
+#define WILDFIRE_HAE_ADDRESS (&alpha_mv.hae_cache)
#if CIA_ONE_HAE_WINDOW
#define CIA_HAE_ADDRESS (&alpha_mv.hae_cache)
@@ -28,6 +30,7 @@
seems like such a pain. Define this to get things to compile. */
#define JENSEN_IACK_SC 1
#define T2_IACK_SC 1
+#define WILDFIRE_IACK_SC 1 /* FIXME */
/*
@@ -91,6 +94,8 @@
#define DO_POLARIS_IO IO(POLARIS,polaris)
#define DO_T2_IO IO(T2,t2)
#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami)
+#define DO_TITAN_IO IO(TITAN,titan)
+#define DO_WILDFIRE_IO IO(WILDFIRE,wildfire)
#define DO_PYXIS_IO IO_LITE(CIA,cia_bwx), \
pci_ops: &CAT(cia,_pci_ops)
@@ -107,6 +112,8 @@
#define DO_POLARIS_BUS BUS(polaris)
#define DO_T2_BUS BUS(t2)
#define DO_TSUNAMI_BUS BUS(tsunami)
+#define DO_TITAN_BUS BUS(titan)
+#define DO_WILDFIRE_BUS BUS(wildfire)
/*
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 238b4004f..d55af89c6 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -230,7 +230,6 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
struct file *file = NULL;
unsigned long ret = -EBADF;
- down(&current->mm->mmap_sem);
lock_kernel();
#if 0
if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
@@ -243,12 +242,13 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
goto out;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ down(&current->mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flags, off);
+ up(&current->mm->mmap_sem);
if (file)
fput(file);
out:
unlock_kernel();
- up(&current->mm->mmap_sem);
return ret;
}
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index f9a79c1d6..39de16465 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -25,11 +25,13 @@
*/
const char *const pci_io_names[] = {
- "PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3"
+ "PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3",
+ "PCI IO bus 4", "PCI IO bus 5", "PCI IO bus 6", "PCI IO bus 7"
};
const char *const pci_mem_names[] = {
- "PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3"
+ "PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3",
+ "PCI mem bus 4", "PCI mem bus 5", "PCI mem bus 6", "PCI mem bus 7"
};
const char pci_hae0_name[] = "HAE0";
@@ -266,6 +268,7 @@ pcibios_fixup_bus(struct pci_bus *bus)
struct pci_controler *hose = (struct pci_controler *) bus->sysdata;
struct list_head *ln;
+ /* ???? */
bus->resource[0] = hose->io_space;
bus->resource[1] = hose->mem_space;
@@ -291,15 +294,14 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
u32 reg;
if (resource < PCI_ROM_RESOURCE)
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
else if (resource == PCI_ROM_RESOURCE)
where = dev->rom_base_reg;
else {
- /* Don't update non-standard resources here */
- return;
+ return; /* Don't update non-standard resources here. */
}
- /* Point root at the hose root */
+ /* Point root at the hose root. */
if (res->flags & IORESOURCE_IO)
root = hose->io_space;
if (res->flags & IORESOURCE_MEM)
@@ -431,6 +433,11 @@ pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
bridge->resource[0].end = bridge->resource[0].start + inner.io_end;
bridge->resource[1].end = bridge->resource[1].start + inner.mem_end;
+ bridge->resource[PCI_BRIDGE_RESOURCES].end =
+ bridge->resource[PCI_BRIDGE_RESOURCES].start + inner.io_end;
+ bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
+ bridge->resource[PCI_BRIDGE_RESOURCES+1].start + inner.mem_end;
+
/* adjust parent's resource requirements */
if (outer) {
outer->io_end = ROUND_UP(outer->io_end, 4*1024);
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 5a36aa578..cadf69b58 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -97,10 +97,6 @@ iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
}
if (i < n) {
- /* Reached the end. Flush the TLB and restart the
- search from the beginning. */
- alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
-
p = 0, i = 0;
while (i < n && p+i < nent) {
if (ptes[p+i])
@@ -139,7 +135,7 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
p[i] = 0;
}
-/* Map a single buffer of the indicate size for PCI DMA in streaming
+/* Map a single buffer of the indicated size for PCI DMA in streaming
mode. The 32-bit PCI bus mastering address to use is returned.
Once the device is given the dma address, the device owns this memory
until either pci_unmap_single or pci_dma_sync_single is performed. */
@@ -201,6 +197,7 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction)
DBGA("pci_map_single: [%p,%lx] np %ld -> sg %x from %p\n",
cpu_addr, size, npages, ret, __builtin_return_address(0));
+ alpha_mv.mv_pci_tbi(hose, ret, ret + size - 1);
return ret;
}
@@ -250,10 +247,6 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
iommu_arena_free(arena, dma_ofs, npages);
- /* If we're freeing ptes above the `next_entry' pointer, they
- may have snuck back into the TLB since the last wrap flush.
- We need to flush the TLB before reallocating these. */
- if (dma_ofs >= arena->next_entry)
alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
DBGA("pci_unmap_single: sg [%x,%lx] np %ld from %p\n",
@@ -441,6 +434,8 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
#endif
} while (++sg < end && (int) sg->dma_address < 0);
+ alpha_mv.mv_pci_tbi(arena->hose, out->dma_address,
+ out->dma_address+out->dma_length-1);
return 1;
}
@@ -574,10 +569,6 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
if (fend < tend) fend = tend;
}
- /* If we're freeing ptes above the `next_entry' pointer, they
- may have snuck back into the TLB since the last wrap flush.
- We need to flush the TLB before reallocating these. */
- if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry)
alpha_mv.mv_pci_tbi(hose, fbeg, fend);
DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg));
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index e141df202..5463c9fec 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -61,6 +61,13 @@ extern void t2_init_arch(void);
extern void t2_machine_check(u64, u64, struct pt_regs *);
#define t2_pci_tbi ((void *)0)
+/* core_titan.c */
+extern struct pci_ops titan_pci_ops;
+extern void titan_init_arch(void);
+extern void titan_kill_arch(int);
+extern void titan_machine_check(u64, u64, struct pt_regs *);
+extern void titan_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
+
/* core_tsunami.c */
extern struct pci_ops tsunami_pci_ops;
extern void tsunami_init_arch(void);
@@ -68,9 +75,19 @@ extern void tsunami_kill_arch(int);
extern void tsunami_machine_check(u64, u64, struct pt_regs *);
extern void tsunami_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
+/* core_wildfire.c */
+extern struct pci_ops wildfire_pci_ops;
+extern void wildfire_init_arch(void);
+extern void wildfire_kill_arch(int);
+extern void wildfire_machine_check(u64, u64, struct pt_regs *);
+extern void wildfire_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
+
/* setup.c */
extern unsigned long srm_hae;
extern int boot_cpuid;
+extern int srmcons_output;
+extern void register_srm_console(void);
+extern void unregister_srm_console(void);
/* smp.c */
extern void setup_smp(void);
@@ -129,7 +146,8 @@ extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
/* ../mm/init.c */
-void srm_paging_stop(void);
+extern void switch_to_system_map(void);
+extern void srm_paging_stop(void);
/* irq.c */
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index b79d42257..09fcfd787 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -246,18 +246,23 @@ sys_ptrace(long request, long pid, long addr, long data,
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->flags |= PF_PTRACED;
+ if (current->ptrace & PT_PTRACED)
+ goto out_notsk;
+ /* set the ptrace bit in the process ptrace flags. */
+ current->ptrace |= PT_PTRACED;
ret = 0;
- goto out;
+ goto out_notsk;
}
if (pid == 1) /* you may not mess with init */
- goto out;
+ goto out_notsk;
ret = -ESRCH;
- if (!(child = find_task_by_pid(pid)))
- goto out;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out_notsk;
if (request == PTRACE_ATTACH) {
ret = -EPERM;
if (child == current)
@@ -273,20 +278,22 @@ sys_ptrace(long request, long pid, long addr, long data,
&& !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
+ if (child->ptrace & PT_PTRACED)
goto out;
- child->flags |= PF_PTRACED;
+ child->ptrace |= PT_PTRACED;
+ write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
+ write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
goto out;
}
ret = -ESRCH;
- if (!(child->flags & PF_PTRACED)) {
+ if (!(child->ptrace & PT_PTRACED)) {
DBG(DBG_MEM, ("child not traced\n"));
goto out;
}
@@ -343,9 +350,9 @@ sys_ptrace(long request, long pid, long addr, long data,
if ((unsigned long) data > _NSIG)
goto out;
if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
+ child->ptrace |= PT_TRACESYS;
else
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
wake_up_process(child);
/* make sure single-step breakpoint is gone. */
@@ -373,7 +380,7 @@ sys_ptrace(long request, long pid, long addr, long data,
if ((unsigned long) data > _NSIG)
goto out;
child->thread.bpt_nsaved = -1; /* mark single-stepping */
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
@@ -384,12 +391,14 @@ sys_ptrace(long request, long pid, long addr, long data,
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
wake_up_process(child);
child->exit_code = data;
+ write_lock_irq(&tasklist_lock);
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
SET_LINKS(child);
+ write_unlock_irq(&tasklist_lock);
/* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child);
ret = 0;
@@ -400,6 +409,8 @@ sys_ptrace(long request, long pid, long addr, long data,
goto out;
}
out:
+ free_task_struct(child);
+ out_notsk:
unlock_kernel();
return ret;
}
@@ -407,8 +418,8 @@ sys_ptrace(long request, long pid, long addr, long data,
asmlinkage void
syscall_trace(void)
{
- if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+ != (PT_PTRACED|PT_TRACESYS))
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 1eab8fc5b..988c3cbec 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -34,6 +34,15 @@
#include <linux/blk.h>
#endif
+#include <linux/notifier.h>
+extern struct notifier_block *panic_notifier_list;
+static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
+static struct notifier_block alpha_panic_block = {
+ alpha_panic_event,
+ NULL,
+ INT_MAX /* try to do it first */
+};
+
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -42,6 +51,7 @@
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/mmu_context.h>
+#include <asm/console.h>
#include "proto.h"
#include "pci_impl.h"
@@ -53,6 +63,17 @@ unsigned long srm_hae;
/* Which processor we booted from. */
int boot_cpuid;
+/* Using SRM callbacks for initial console output. This works from
+ setup_arch() time through the end of init_IRQ(), as those places
+ are under our control.
+
+ By default, OFF; set it with a bootcommand arg of "srmcons".
+*/
+int srmcons_output = 0;
+
+/* Enforce a memory size limit; useful for testing. By default, none. */
+unsigned long mem_size_limit = 0;
+
#ifdef CONFIG_ALPHA_GENERIC
struct alpha_machine_vector alpha_mv;
int alpha_using_srm;
@@ -139,6 +160,7 @@ WEAK(noritake_mv);
WEAK(noritake_primo_mv);
WEAK(p2k_mv);
WEAK(pc164_mv);
+WEAK(privateer_mv);
WEAK(rawhide_mv);
WEAK(ruffian_mv);
WEAK(rx164_mv);
@@ -147,6 +169,7 @@ WEAK(sable_gamma_mv);
WEAK(sx164_mv);
WEAK(takara_mv);
WEAK(webbrick_mv);
+WEAK(wildfire_mv);
WEAK(xl_mv);
WEAK(xlt_mv);
@@ -202,14 +225,33 @@ reserve_std_resources(void)
for ((cluster) = (memdesc)->cluster, (i) = 0; \
(i) < (memdesc)->numclusters; (i)++, (cluster)++)
+static unsigned long __init
+get_mem_size_limit(char *s)
+{
+ unsigned long end = 0;
+ char *from = s;
+
+ end = simple_strtoul(from, &from, 0);
+ if ( *from == 'K' || *from == 'k' ) {
+ end = end << 10;
+ from++;
+ } else if ( *from == 'M' || *from == 'm' ) {
+ end = end << 20;
+ from++;
+ } else if ( *from == 'G' || *from == 'g' ) {
+ end = end << 30;
+ from++;
+ }
+ return end >> PAGE_SHIFT; /* Return the PFN of the limit. */
+}
+
static void __init
-setup_memory(void)
+setup_memory(void * kernel_end)
{
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. */
@@ -232,15 +274,23 @@ setup_memory(void)
max_low_pfn = end;
}
- /* Find the end of the kernel memory. */
- start_pfn = PFN_UP(virt_to_phys(_end));
+ if (mem_size_limit && max_low_pfn >= mem_size_limit)
+ {
+ printk("setup: forcing memory size to %ldK (from %ldK).\n",
+ mem_size_limit << (PAGE_SHIFT - 10),
+ max_low_pfn << (PAGE_SHIFT - 10));
+ max_low_pfn = mem_size_limit;
+ }
+
+ /* Find the end of the memory used by the kernel. */
+ start_pfn = PFN_UP(virt_to_phys(kernel_end));
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 need to know how many physically contiguous pages
we'll need for the bootmap. */
bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
@@ -307,14 +357,14 @@ setup_memory(void)
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))) {
+ if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
printk("initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ "(0x%08lx > 0x%p)\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),
+ reserve_bootmem(virt_to_phys((void *)initrd_start),
INITRD_SIZE);
}
}
@@ -346,20 +396,98 @@ page_is_ram(unsigned long pfn)
#undef PFN_PHYS
#undef PFN_MAX
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
+/*
+ * Manage the SRM callbacks as a "console".
+ */
+static struct console srmcons;
+
+void __init register_srm_console(void)
+{
+ register_console(&srmcons);
+}
+
+void __init unregister_srm_console(void)
+{
+ unregister_console(&srmcons);
+}
+
+static void srm_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ srm_printk(s);
+}
+
+static kdev_t srm_console_device(struct console *c)
+{
+ /* Huh? */
+ return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int srm_console_wait_key(struct console *co)
+{
+ /* Huh? */
+ return 1;
+}
+
+static int __init srm_console_setup(struct console *co, char *options)
+{
+ return 1;
+}
+
+static struct console srmcons = {
+ "srm0",
+ srm_console_write,
+ NULL,
+ srm_console_device,
+ srm_console_wait_key,
+ NULL,
+ srm_console_setup,
+ CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
+ -1,
+ 0,
+ NULL
+};
+
+#else
+void __init register_srm_console(void)
+{
+}
+void __init unregister_srm_console(void)
+{
+}
+#endif
+
void __init
setup_arch(char **cmdline_p)
{
struct alpha_machine_vector *vec = NULL;
struct percpu_struct *cpu;
char *type_name, *var_name, *p;
+ extern char _end;
+ void * kernel_end = &_end; /* end of kernel */
hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
boot_cpuid = hard_smp_processor_id();
+ /* Register a call for panic conditions. */
+ notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
+
+#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. */
+ alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#endif
+
+ /* If we are using SRM, we want to allow callbacks
+ as early as possible, so do this NOW, and then
+ they should work immediately thereafter.
+ */
+ kernel_end = callback_init(kernel_end);
+
/*
* Locate the command line.
*/
-
/* Hack for Jensen... since we're restricted to 8 or 16 chars for
boot flags depending on the boot mode, we need some shorthand.
This should do for installation. */
@@ -375,7 +503,6 @@ setup_arch(char **cmdline_p)
/*
* Process command-line arguments.
*/
-
for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
if (strncmp(p, "alpha_mv=", 9) == 0) {
vec = get_sysvec_byname(p+9);
@@ -385,15 +512,27 @@ setup_arch(char **cmdline_p)
est_cycle_freq = simple_strtol(p+6, NULL, 0);
continue;
}
+ if (strncmp(p, "mem=", 4) == 0) {
+ mem_size_limit = get_mem_size_limit(p+4);
+ continue;
+ }
+ if (strncmp(p, "srmcons", 7) == 0) {
+ srmcons_output = 1;
+ continue;
+ }
}
- /* Replace the command line, not that we've killed it with strtok. */
+ /* Replace the command line, now that we've killed it with strtok. */
strcpy(command_line, saved_command_line);
+ /* If we want SRM console printk echoing early, do it now. */
+ if (alpha_using_srm && srmcons_output) {
+ register_srm_console();
+ }
+
/*
* Indentify and reconfigure for the current system.
*/
-
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
&type_name, &var_name);
if (*var_name == '0')
@@ -415,12 +554,6 @@ setup_arch(char **cmdline_p)
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. */
- alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#endif
-
printk("Booting "
#ifdef CONFIG_ALPHA_GENERIC
"GENERIC "
@@ -433,10 +566,9 @@ setup_arch(char **cmdline_p)
printk("Command line: %s\n", command_line);
/*
- * Sync with the HAE
+ * Sync up the HAE.
+ * Save the SRM's current value for restoration.
*/
-
- /* Save the SRM's current value for restoration. */
srm_hae = *alpha_mv.hae_register;
__set_hae(alpha_mv.hae_cache);
@@ -444,7 +576,7 @@ setup_arch(char **cmdline_p)
wrmces(0x7);
/* Find our memory. */
- setup_memory();
+ setup_memory(kernel_end);
/* Initialize the machine. Usually has to do with setting up
DMA windows and the like. */
@@ -499,7 +631,7 @@ 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", "Eiger"
+ "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan"
};
static char unofficial_names[][8] = {"100", "Ruffian"};
@@ -523,6 +655,11 @@ static char rawhide_names[][16] = {
};
static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
+static char titan_names[][16] = {
+ "0", "Privateer"
+};
+static int titan_indices[] = {0,1};
+
static char tsunami_names[][16] = {
"0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
"Goldrush", "Webbrick", "Catamaran"
@@ -569,9 +706,10 @@ get_sysvec(long type, long variation, long cpu)
&takara_mv,
NULL, /* Yukon */
NULL, /* Tsunami -- see variation. */
- NULL, /* Wildfire */
+ &wildfire_mv, /* Wildfire */
NULL, /* CUSCO */
&eiger_mv, /* Eiger */
+ NULL, /* Titan */
};
static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata =
@@ -609,6 +747,12 @@ get_sysvec(long type, long variation, long cpu)
&eb66p_mv
};
+ static struct alpha_machine_vector *titan_vecs[] __initlocaldata =
+ {
+ NULL,
+ &privateer_mv, /* privateer */
+ };
+
static struct alpha_machine_vector *tsunami_vecs[] __initlocaldata =
{
NULL,
@@ -665,6 +809,10 @@ get_sysvec(long type, long variation, long cpu)
if (member < N(eb66_indices))
vec = eb66_vecs[eb66_indices[member]];
break;
+ case ST_DEC_TITAN:
+ if (member < N(titan_indices))
+ vec = titan_vecs[titan_indices[member]];
+ break;
case ST_DEC_TSUNAMI:
if (member < N(tsunami_indices))
vec = tsunami_vecs[tsunami_indices[member]];
@@ -723,6 +871,7 @@ get_sysvec_byname(const char *name)
&noritake_primo_mv,
&p2k_mv,
&pc164_mv,
+ &privateer_mv,
&rawhide_mv,
&ruffian_mv,
&rx164_mv,
@@ -731,6 +880,7 @@ get_sysvec_byname(const char *name)
&sx164_mv,
&takara_mv,
&webbrick_mv,
+ &wildfire_mv,
&xl_mv,
&xlt_mv
};
@@ -801,6 +951,10 @@ get_sysnames(long type, long variation,
if (member < N(rawhide_indices))
*variation_name = rawhide_names[rawhide_indices[member]];
break;
+ case ST_DEC_TITAN:
+ if (member < N(titan_indices))
+ *variation_name = titan_names[titan_indices[member]];
+ break;
case ST_DEC_TSUNAMI:
if (member < N(tsunami_indices))
*variation_name = tsunami_names[tsunami_indices[member]];
@@ -873,7 +1027,7 @@ int get_cpuinfo(char *buffer)
static char cpu_names[][8] = {
"EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
- "EV6", "PCA56", "PCA57", "EV67"
+ "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL"
};
struct percpu_struct *cpu;
@@ -936,3 +1090,16 @@ int get_cpuinfo(char *buffer)
return len;
}
+
+static int alpha_panic_event(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+#if 1
+ /* FIXME FIXME FIXME */
+ /* If we are using SRM and serial console, just hard halt here. */
+ if (alpha_using_srm && srmcons_output)
+ __halt();
+#endif
+ return NOTIFY_DONE;
+}
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 1f70c98e6..db8cacbc9 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -651,7 +651,7 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c
index caab7accc..0b2db18ab 100644
--- a/arch/alpha/kernel/smc37c669.c
+++ b/arch/alpha/kernel/smc37c669.c
@@ -2588,6 +2588,9 @@ void __init SMC669_Init ( int index )
);
SMC37c669_enable_device( FLOPPY_0 );
+ /* Wake up sometimes forgotten floppy, especially on DP264. */
+ outb(0xc, 0x3f2);
+
SMC37c669_disable_device( IDE_0 );
#if SMC_DEBUG
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 1ddaaf74d..b812e2c64 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -212,8 +212,19 @@ smp_tune_scheduling (void)
freq = hwrpb->cycle_freq ? : est_cycle_freq;
+#if 0
/* Magic estimation stolen from x86 port. */
- cacheflush_time = freq / 1024 * on_chip_cache / 5000;
+ cacheflush_time = freq / 1024L * on_chip_cache / 5000L;
+
+ printk("Using heuristic of %d cycles.\n",
+ cacheflush_time);
+#else
+ /* Magic value to force potential preemption of other CPUs. */
+ cacheflush_time = INT_MAX;
+
+ printk("Using heuristic of %d cycles.\n",
+ cacheflush_time);
+#endif
}
/*
@@ -325,8 +336,8 @@ recv_secondary_console_msg(void)
}
}
- printk(KERN_INFO "recv_secondary_console_msg: on %d "
- "message is '%s'\n", mycpu, buf);
+ DBGS((KERN_INFO "recv_secondary_console_msg: on %d "
+ "message is '%s'\n", mycpu, buf));
}
hwrpb->txrdy = 0;
@@ -361,8 +372,10 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
hwpcb->flags = idle->thread.pal_flags;
hwpcb->res1 = hwpcb->res2 = 0;
+#if 0
DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique));
+#endif
DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
cpuid, idle->state, idle->thread.pal_flags));
@@ -738,8 +751,10 @@ handle_ipi(struct pt_regs *regs)
unsigned long *pending_ipis = &ipi_data[this_cpu].bits;
unsigned long ops;
- DBGS(("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n",
+#if 0
+ DBGS(("handle_ipi: on CPU %d ops 0x%lx PC 0x%lx\n",
this_cpu, *pending_ipis, regs->pc));
+#endif
mb(); /* Order interrupt and bit testing. */
while ((ops = xchg(pending_ipis, 0)) != 0) {
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index c10018fff..475b477bd 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -36,7 +36,7 @@
/* Note mask bit is true for ENABLED irqs. */
static unsigned long cached_irq_mask;
/* dp264 boards handle at max four CPUs */
-static unsigned long cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
+static unsigned long cpu_irq_affinity[4] = { 0UL, 0UL, 0UL, 0UL };
spinlock_t dp264_irq_lock = SPIN_LOCK_UNLOCKED;
@@ -52,6 +52,7 @@ tsunami_update_irq_hw(unsigned long mask)
volatile unsigned long *dim0, *dim1, *dim2, *dim3;
unsigned long mask0, mask1, mask2, mask3, dummy;
+ mask &= ~isa_enable;
mask0 = mask & cpu_irq_affinity[0];
mask1 = mask & cpu_irq_affinity[1];
mask2 = mask & cpu_irq_affinity[2];
@@ -170,7 +171,6 @@ cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
aff &= ~(1UL << irq);
cpu_irq_affinity[cpu] = aff;
}
-
}
static void
@@ -275,7 +275,12 @@ clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
irq = (vector - 0x800) >> 4;
- /*
+#if 0
+ printk("clipper_srm_device_interrupt: vector 0x%lx IRQ %d cpu %d\n",
+ vector, irq, smp_processor_id());
+#endif
+
+/*
* The SRM console reports PCI interrupts with a vector calculated by:
*
* 0x900 + (0x10 * DRIR-bit)
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index f436b4902..d939b2c21 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -185,8 +185,8 @@ static void
mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
-#define MCHK_NO_DEVSEL 0x205L
-#define MCHK_NO_TABT 0x204L
+#define MCHK_NO_DEVSEL 0x205U
+#define MCHK_NO_TABT 0x204U
struct el_common *mchk_header;
unsigned int code;
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
new file mode 100644
index 000000000..5b3011d07
--- /dev/null
+++ b/arch/alpha/kernel/sys_titan.c
@@ -0,0 +1,392 @@
+/*
+ * linux/arch/alpha/kernel/sys_titan.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996, 1999 Jay A Estabrook
+ * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1999, 2000 Jeff Wiedemeier
+ *
+ * Code supporting TITAN systems (EV6+TITAN), currently:
+ * Privateer
+ */
+
+#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/pgtable.h>
+#include <asm/core_titan.h>
+#include <asm/hwrpb.h>
+
+#include "proto.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
+
+/* Note mask bit is true for ENABLED irqs. */
+static unsigned long cached_irq_mask;
+/* Titan boards handle at most four CPUs. */
+static unsigned long cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
+
+spinlock_t titan_irq_lock = SPIN_LOCK_UNLOCKED;
+
+static void
+titan_update_irq_hw(unsigned long mask)
+{
+ register titan_cchip *cchip = TITAN_cchip;
+ unsigned long isa_enable = 1UL << 55;
+ register int bcpu = boot_cpuid;
+
+#ifdef CONFIG_SMP
+ register unsigned long cpm = cpu_present_mask;
+ volatile unsigned long *dim0, *dim1, *dim2, *dim3;
+ unsigned long mask0, mask1, mask2, mask3, dummy;
+
+ mask &= ~isa_enable;
+ mask0 = mask & cpu_irq_affinity[0];
+ mask1 = mask & cpu_irq_affinity[1];
+ mask2 = mask & cpu_irq_affinity[2];
+ mask3 = mask & cpu_irq_affinity[3];
+
+ if (bcpu == 0) mask0 |= isa_enable;
+ else if (bcpu == 1) mask1 |= isa_enable;
+ else if (bcpu == 2) mask2 |= isa_enable;
+ else mask3 |= isa_enable;
+
+ dim0 = &cchip->dim0.csr;
+ dim1 = &cchip->dim1.csr;
+ dim2 = &cchip->dim2.csr;
+ dim3 = &cchip->dim3.csr;
+ if ((cpm & 1) == 0) dim0 = &dummy;
+ if ((cpm & 2) == 0) dim1 = &dummy;
+ if ((cpm & 4) == 0) dim2 = &dummy;
+ if ((cpm & 8) == 0) dim3 = &dummy;
+
+ *dim0 = mask0;
+ *dim1 = mask1;
+ *dim2 = mask2;
+ *dim3 = mask3;
+ mb();
+ *dim0;
+ *dim1;
+ *dim2;
+ *dim3;
+#else
+ volatile unsigned long *dimB;
+ if (bcpu == 0) dimB = &cchip->dim0.csr;
+ else if (bcpu == 1) dimB = &cchip->dim1.csr;
+ else if (bcpu == 2) dimB = &cchip->dim2.csr;
+ else if (bcpu == 3) dimB = &cchip->dim3.csr;
+
+ *dimB = mask | isa_enable;
+ mb();
+ *dimB;
+#endif
+}
+
+static inline void
+privateer_enable_irq(unsigned int irq)
+{
+ spin_lock(&titan_irq_lock);
+ cached_irq_mask |= 1UL << (irq - 16);
+ titan_update_irq_hw(cached_irq_mask);
+ spin_unlock(&titan_irq_lock);
+}
+
+static inline void
+privateer_disable_irq(unsigned int irq)
+{
+ spin_lock(&titan_irq_lock);
+ cached_irq_mask &= ~(1UL << (irq - 16));
+ titan_update_irq_hw(cached_irq_mask);
+ spin_unlock(&titan_irq_lock);
+}
+
+static unsigned int
+privateer_startup_irq(unsigned int irq)
+{
+ privateer_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void
+privateer_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ privateer_enable_irq(irq);
+}
+
+static void
+cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
+{
+ int cpu;
+
+ for (cpu = 0; cpu < 4; cpu++) {
+ if (affinity & (1UL << cpu))
+ cpu_irq_affinity[cpu] |= 1UL << irq;
+ else
+ cpu_irq_affinity[cpu] &= ~(1UL << irq);
+ }
+
+}
+
+static void
+privateer_set_affinity(unsigned int irq, unsigned long affinity)
+{
+ spin_lock(&titan_irq_lock);
+ cpu_set_irq_affinity(irq - 16, affinity);
+ titan_update_irq_hw(cached_irq_mask);
+ spin_unlock(&titan_irq_lock);
+}
+
+static struct hw_interrupt_type privateer_irq_type = {
+ typename: "PRIVATEER",
+ startup: privateer_startup_irq,
+ shutdown: privateer_disable_irq,
+ enable: privateer_enable_irq,
+ disable: privateer_disable_irq,
+ ack: privateer_disable_irq,
+ end: privateer_end_irq,
+ set_affinity: privateer_set_affinity,
+};
+
+static void
+privateer_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ printk("privateer_device_interrupt: NOT IMPLEMENTED YET!! \n");
+}
+
+static void
+privateer_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq;
+
+ irq = (vector - 0x800) >> 4;
+ handle_irq(irq, regs);
+}
+
+
+static void __init
+init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
+{
+ long i;
+ for(i = imin; i <= imax; ++i) {
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[i].handler = ops;
+ }
+}
+
+static void __init
+privateer_init_irq(void)
+{
+ extern asmlinkage void entInt(void);
+ int cpu;
+
+ 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 = privateer_srm_device_interrupt;
+
+ titan_update_irq_hw(0UL);
+
+ init_i8259a_irqs();
+ init_titan_irqs(&privateer_irq_type, 16, 63 + 16);
+}
+
+/*
+ * Privateer PCI Fixup configuration.
+ *
+ * PCHIP 0 BUS 0 (Hose 0)
+ *
+ * IDSEL Dev What
+ * ----- --- ----
+ * 18 7 Embedded Southbridge
+ * 19 8 Slot 0
+ * 20 9 Slot 1
+ * 21 10 Slot 2
+ * 22 11 Slot 3
+ * 23 12 Embedded HotPlug controller
+ * 27 16 Embedded Southbridge IDE
+ * 29 18 Embedded Southbridge PMU
+ * 31 20 Embedded Southbridge USB
+ *
+ * PCHIP 1 BUS 0 (Hose 1)
+ *
+ * IDSEL Dev What
+ * ----- --- ----
+ * 12 1 Slot 0
+ * 13 2 Slot 1
+ * 17 6 Embedded hotPlug controller
+ *
+ * PCHIP 0 BUS 1 (Hose 2)
+ *
+ * IDSEL What
+ * ----- ----
+ * NONE AGP
+ *
+ * PCHIP 1 BUS 1 (Hose 3)
+ *
+ * IDSEL Dev What
+ * ----- --- ----
+ * 12 1 Slot 0
+ * 13 2 Slot 1
+ * 17 6 Embedded hotPlug controller
+ *
+ * Summary @ TITAN_CSR_DIM0:
+ * Bit Meaning
+ * 0-7 Unused
+ * 8 PCHIP 0 BUS 1 YUKON (if present)
+ * 9 PCHIP 1 BUS 1 YUKON
+ * 10 PCHIP 1 BUS 0 YUKON
+ * 11 PCHIP 0 BUS 0 YUKON
+ * 12 PCHIP 0 BUS 0 SLOT 2 INT A
+ * 13 PCHIP 0 BUS 0 SLOT 2 INT B
+ * 14 PCHIP 0 BUS 0 SLOT 2 INT C
+ * 15 PCHIP 0 BUS 0 SLOT 2 INT D
+ * 16 PCHIP 0 BUS 0 SLOT 3 INT A
+ * 17 PCHIP 0 BUS 0 SLOT 3 INT B
+ * 18 PCHIP 0 BUS 0 SLOT 3 INT C
+ * 19 PCHIP 0 BUS 0 SLOT 3 INT D
+ * 20 PCHIP 0 BUS 0 SLOT 0 INT A
+ * 21 PCHIP 0 BUS 0 SLOT 0 INT B
+ * 22 PCHIP 0 BUS 0 SLOT 0 INT C
+ * 23 PCHIP 0 BUS 0 SLOT 0 INT D
+ * 24 PCHIP 0 BUS 0 SLOT 1 INT A
+ * 25 PCHIP 0 BUS 0 SLOT 1 INT B
+ * 26 PCHIP 0 BUS 0 SLOT 1 INT C
+ * 27 PCHIP 0 BUS 0 SLOT 1 INT D
+ * 28 PCHIP 1 BUS 0 SLOT 0 INT A
+ * 29 PCHIP 1 BUS 0 SLOT 0 INT B
+ * 30 PCHIP 1 BUS 0 SLOT 0 INT C
+ * 31 PCHIP 1 BUS 0 SLOT 0 INT D
+ * 32 PCHIP 1 BUS 0 SLOT 1 INT A
+ * 33 PCHIP 1 BUS 0 SLOT 1 INT B
+ * 34 PCHIP 1 BUS 0 SLOT 1 INT C
+ * 35 PCHIP 1 BUS 0 SLOT 1 INT D
+ * 36 PCHIP 1 BUS 1 SLOT 0 INT A
+ * 37 PCHIP 1 BUS 1 SLOT 0 INT B
+ * 38 PCHIP 1 BUS 1 SLOT 0 INT C
+ * 39 PCHIP 1 BUS 1 SLOT 0 INT D
+ * 40 PCHIP 1 BUS 1 SLOT 1 INT A
+ * 41 PCHIP 1 BUS 1 SLOT 1 INT B
+ * 42 PCHIP 1 BUS 1 SLOT 1 INT C
+ * 43 PCHIP 1 BUS 1 SLOT 1 INT D
+ * 44 AGP INT A
+ * 45 AGP INT B
+ * 46-47 Unused
+ * 49 Reserved for Sleep mode
+ * 50 Temperature Warning (optional)
+ * 51 Power Warning (optional)
+ * 52 Reserved
+ * 53 South Bridge NMI
+ * 54 South Bridge SMI INT
+ * 55 South Bridge ISA Interrupt
+ * 56-58 Unused
+ * 59 PCHIP1_C_ERROR
+ * 60 PCHIP0_C_ERROR
+ * 61 PCHIP1_H_ERROR
+ * 62 PCHIP0_H_ERROR
+ * 63 Reserved
+ *
+ */
+static int __init
+privateer_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ u8 irq;
+
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_LINE,
+ &irq);
+
+ /* is it routed through ISA? */
+ if ((irq & 0xF0) == 0xE0)
+ return (int)irq;
+
+ return (int)irq + 16; /* HACK -- this better only be called once */
+}
+
+#ifdef CONFIG_VGA_HOSE
+static struct pci_controler * __init
+privateer_vga_hose_select(struct pci_controler *h1, struct pci_controler *h2)
+{
+ struct pci_controler *hose = h1;
+ int agp1, agp2;
+
+ /* which hose(s) are agp? */
+ agp1 = (0 != (TITAN_agp & (1 << h1->index)));
+ agp2 = (0 != (TITAN_agp & (1 << h2->index)));
+
+ hose = h1; /* default to h1 */
+ if (agp1 ^ agp2) {
+ if (agp2) hose = h2; /* take agp if only one */
+ } else if (h2->index < h1->index)
+ hose = h2; /* first hose if 2xpci or 2xagp */
+
+ return hose;
+}
+#endif
+
+static void __init
+privateer_init_pci(void)
+{
+ common_init_pci();
+ SMC669_Init(0);
+#ifdef CONFIG_VGA_HOSE
+ locate_and_init_vga(privateer_vga_hose_select);
+#endif
+}
+
+void
+privateer_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ /* only handle system events here */
+ if (vector != SCB_Q_SYSEVENT)
+ return titan_machine_check(vector, la_ptr, regs);
+
+ /* it's a system event, handle it here */
+ printk("PRIVATEER 680 Machine Check on CPU %d\n", smp_processor_id());
+}
+
+
+/*
+ * The System Vectors
+ */
+
+struct alpha_machine_vector privateer_mv __initmv = {
+ vector_name: "PRIVATEER",
+ DO_EV6_MMU,
+ DO_DEFAULT_RTC,
+ DO_TITAN_IO,
+ DO_TITAN_BUS,
+ machine_check: privateer_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
+
+ nr_irqs: 80, /* 64 + 16 */
+ device_interrupt: privateer_device_interrupt,
+
+ init_arch: titan_init_arch,
+ init_irq: privateer_init_irq,
+ init_rtc: common_init_rtc,
+ init_pci: privateer_init_pci,
+ kill_arch: titan_kill_arch,
+ pci_map_irq: privateer_map_irq,
+ pci_swizzle: common_swizzle,
+};
+ALIAS_MV(privateer)
diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c
new file mode 100644
index 000000000..7aa49f50b
--- /dev/null
+++ b/arch/alpha/kernel/sys_wildfire.c
@@ -0,0 +1,362 @@
+/*
+ * linux/arch/alpha/kernel/sys_wildfire.c
+ *
+ * Wildfire support.
+ *
+ * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
+ */
+
+#include <linux/config.h>
+#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/pgtable.h>
+#include <asm/core_wildfire.h>
+#include <asm/hwrpb.h>
+
+#include "proto.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
+
+static unsigned long cached_irq_mask[WILDFIRE_NR_IRQS/(sizeof(long)*8)];
+
+spinlock_t wildfire_irq_lock = SPIN_LOCK_UNLOCKED;
+
+static int doing_init_irq_hw = 0;
+
+static void
+wildfire_update_irq_hw(unsigned int irq)
+{
+ int qbbno = (irq >> 8) & (WILDFIRE_MAX_QBB - 1);
+ int pcano = (irq >> 6) & (WILDFIRE_PCA_PER_QBB - 1);
+ wildfire_pca *pca;
+ volatile unsigned long * enable0;
+
+ if (!WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
+ if (!doing_init_irq_hw) {
+ printk(KERN_ERR "wildfire_update_irq_hw:"
+ " got irq %d for non-existent PCA %d"
+ " on QBB %d.\n",
+ irq, pcano, qbbno);
+ }
+ return;
+ }
+
+ pca = WILDFIRE_pca(qbbno, pcano);
+ enable0 = (unsigned long *) &pca->pca_int[0].enable; /* ??? */
+
+ *enable0 = cached_irq_mask[qbbno * WILDFIRE_PCA_PER_QBB + pcano];
+ mb();
+ *enable0;
+}
+
+static void __init
+wildfire_init_irq_hw(void)
+{
+#if 0
+ register wildfire_pca * pca = WILDFIRE_pca(0, 0);
+ volatile unsigned long * enable0, * enable1, * enable2, *enable3;
+ volatile unsigned long * target0, * target1, * target2, *target3;
+
+ enable0 = (unsigned long *) &pca->pca_int[0].enable;
+ enable1 = (unsigned long *) &pca->pca_int[1].enable;
+ enable2 = (unsigned long *) &pca->pca_int[2].enable;
+ enable3 = (unsigned long *) &pca->pca_int[3].enable;
+
+ target0 = (unsigned long *) &pca->pca_int[0].target;
+ target1 = (unsigned long *) &pca->pca_int[1].target;
+ target2 = (unsigned long *) &pca->pca_int[2].target;
+ target3 = (unsigned long *) &pca->pca_int[3].target;
+
+ *enable0 = *enable1 = *enable2 = *enable3 = 0;
+
+ *target0 = (1UL<<8) | WILDFIRE_QBB(0);
+ *target1 = *target2 = *target3 = 0;
+
+ mb();
+
+ *enable0; *enable1; *enable2; *enable3;
+ *target0; *target1; *target2; *target3;
+
+#else
+ int i;
+
+ doing_init_irq_hw = 1;
+
+ /* Need to update only once for every possible PCA. */
+ for (i = 0; i < WILDFIRE_NR_IRQS; i+=WILDFIRE_IRQ_PER_PCA)
+ wildfire_update_irq_hw(i);
+
+ doing_init_irq_hw = 0;
+#endif
+}
+
+static void
+wildfire_enable_irq(unsigned int irq)
+{
+ if (irq < 16)
+ i8259a_enable_irq(irq);
+
+ spin_lock(&wildfire_irq_lock);
+ set_bit(irq, &cached_irq_mask);
+ wildfire_update_irq_hw(irq);
+ spin_unlock(&wildfire_irq_lock);
+}
+
+static void
+wildfire_disable_irq(unsigned int irq)
+{
+ if (irq < 16)
+ i8259a_disable_irq(irq);
+
+ spin_lock(&wildfire_irq_lock);
+ clear_bit(irq, &cached_irq_mask);
+ wildfire_update_irq_hw(irq);
+ spin_unlock(&wildfire_irq_lock);
+}
+
+static void
+wildfire_mask_and_ack_irq(unsigned int irq)
+{
+ if (irq < 16)
+ i8259a_mask_and_ack_irq(irq);
+
+ spin_lock(&wildfire_irq_lock);
+ clear_bit(irq, &cached_irq_mask);
+ wildfire_update_irq_hw(irq);
+ spin_unlock(&wildfire_irq_lock);
+}
+
+static unsigned int
+wildfire_startup_irq(unsigned int irq)
+{
+ wildfire_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void
+wildfire_end_irq(unsigned int irq)
+{
+#if 0
+ if (!irq_desc[irq].action)
+ printk("got irq %d\n", irq);
+#endif
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ wildfire_enable_irq(irq);
+}
+
+static struct hw_interrupt_type wildfire_irq_type = {
+ typename: "WILDFIRE",
+ startup: wildfire_startup_irq,
+ shutdown: wildfire_disable_irq,
+ enable: wildfire_enable_irq,
+ disable: wildfire_disable_irq,
+ ack: wildfire_mask_and_ack_irq,
+ end: wildfire_end_irq,
+};
+
+static void __init
+wildfire_init_irq_per_pca(int qbbno, int pcano)
+{
+ int i, irq_bias;
+ unsigned long io_bias;
+ static struct irqaction isa_enable = {
+ handler: no_action,
+ name: "isa_enable",
+ };
+
+ irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
+ + pcano * WILDFIRE_IRQ_PER_PCA;
+
+ /* Only need the following for first PCI bus per PCA. */
+ io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
+
+#if 0
+ outb(0, DMA1_RESET_REG + io_bias);
+ outb(0, DMA2_RESET_REG + io_bias);
+ outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
+ outb(0, DMA2_MASK_REG + io_bias);
+#endif
+
+#if 0
+ /* ??? Not sure how to do this, yet... */
+ init_i8259a_irqs(); /* ??? */
+#endif
+
+ for (i = 0; i < 16; ++i) {
+ if (i == 2)
+ continue;
+ irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[i+irq_bias].handler = &wildfire_irq_type;
+ }
+
+ irq_desc[36+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[36+irq_bias].handler = &wildfire_irq_type;
+ for (i = 40; i < 64; ++i) {
+ irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[i+irq_bias].handler = &wildfire_irq_type;
+ }
+
+ setup_irq(32+irq_bias, &isa_enable);
+}
+
+static void __init
+wildfire_init_irq(void)
+{
+ int qbbno, pcano;
+
+#if 1
+ wildfire_init_irq_hw();
+ init_i8259a_irqs();
+#endif
+
+ for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
+ if (WILDFIRE_QBB_EXISTS(qbbno)) {
+ for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
+ if (WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
+ wildfire_init_irq_per_pca(qbbno, pcano);
+ }
+ }
+ }
+ }
+}
+
+static void
+wildfire_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq;
+
+ irq = (vector - 0x800) >> 4;
+
+ /*
+ * bits 10-8: source QBB ID
+ * bits 7-6: PCA
+ * bits 5-0: irq in PCA
+ */
+
+ handle_irq(irq, regs);
+ return;
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary per PCA (2 PCI or HIPPI buses):
+ *
+ * Bit Meaning
+ * 0-15 ISA
+ *
+ *32 ISA summary
+ *33 SMI
+ *34 NMI
+ *36 builtin QLogic SCSI (or slot 0 if no IO module)
+ *40 Interrupt Line A from slot 2 PCI0
+ *41 Interrupt Line B from slot 2 PCI0
+ *42 Interrupt Line C from slot 2 PCI0
+ *43 Interrupt Line D from slot 2 PCI0
+ *44 Interrupt Line A from slot 3 PCI0
+ *45 Interrupt Line B from slot 3 PCI0
+ *46 Interrupt Line C from slot 3 PCI0
+ *47 Interrupt Line D from slot 3 PCI0
+ *
+ *48 Interrupt Line A from slot 4 PCI1
+ *49 Interrupt Line B from slot 4 PCI1
+ *50 Interrupt Line C from slot 4 PCI1
+ *51 Interrupt Line D from slot 4 PCI1
+ *52 Interrupt Line A from slot 5 PCI1
+ *53 Interrupt Line B from slot 5 PCI1
+ *54 Interrupt Line C from slot 5 PCI1
+ *55 Interrupt Line D from slot 5 PCI1
+ *56 Interrupt Line A from slot 6 PCI1
+ *57 Interrupt Line B from slot 6 PCI1
+ *58 Interrupt Line C from slot 6 PCI1
+ *50 Interrupt Line D from slot 6 PCI1
+ *60 Interrupt Line A from slot 7 PCI1
+ *61 Interrupt Line B from slot 7 PCI1
+ *62 Interrupt Line C from slot 7 PCI1
+ *63 Interrupt Line D from slot 7 PCI1
+ *
+ *
+ * IdSel
+ * 0 Cypress Bridge I/O (ISA summary interrupt)
+ * 1 64 bit PCI 0 option slot 1 (SCSI QLogic builtin)
+ * 2 64 bit PCI 0 option slot 2
+ * 3 64 bit PCI 0 option slot 3
+ * 4 64 bit PCI 1 option slot 4
+ * 5 64 bit PCI 1 option slot 5
+ * 6 64 bit PCI 1 option slot 6
+ * 7 64 bit PCI 1 option slot 7
+ */
+
+static int __init
+wildfire_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ static char irq_tab[8][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { -1, -1, -1, -1, -1}, /* IdSel 0 ISA Bridge */
+ { 36, 36, 36+1, 36+2, 36+3}, /* IdSel 1 SCSI builtin */
+ { 40, 40, 40+1, 40+2, 40+3}, /* IdSel 2 PCI 0 slot 2 */
+ { 44, 44, 44+1, 44+2, 44+3}, /* IdSel 3 PCI 0 slot 3 */
+ { 48, 48, 48+1, 48+2, 48+3}, /* IdSel 4 PCI 1 slot 4 */
+ { 52, 52, 52+1, 52+2, 52+3}, /* IdSel 5 PCI 1 slot 5 */
+ { 56, 56, 56+1, 56+2, 56+3}, /* IdSel 6 PCI 1 slot 6 */
+ { 60, 60, 60+1, 60+2, 60+3}, /* IdSel 7 PCI 1 slot 7 */
+ };
+ const long min_idsel = 0, max_idsel = 7, irqs_per_slot = 5;
+
+ struct pci_controler *hose = dev->sysdata;
+ int irq = COMMON_TABLE_LOOKUP;
+
+ if (irq > 0) {
+ int qbbno = hose->index >> 3;
+ int pcano = (hose->index >> 1) & 3;
+ irq += (qbbno << 8) + (pcano << 6);
+ }
+ return irq;
+}
+
+static void __init
+wildfire_init_pci(void)
+{
+ common_init_pci();
+}
+
+/*
+ * The System Vectors
+ */
+
+struct alpha_machine_vector wildfire_mv __initmv = {
+ vector_name: "WILDFIRE",
+ DO_EV6_MMU,
+ DO_DEFAULT_RTC,
+ DO_WILDFIRE_IO,
+ DO_WILDFIRE_BUS,
+ machine_check: wildfire_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
+
+ nr_irqs: WILDFIRE_NR_IRQS,
+ device_interrupt: wildfire_device_interrupt,
+
+ init_arch: wildfire_init_arch,
+ init_irq: wildfire_init_irq,
+ init_rtc: common_init_rtc,
+ init_pci: wildfire_init_pci,
+ kill_arch: wildfire_kill_arch,
+ pci_map_irq: wildfire_map_irq,
+ pci_swizzle: common_swizzle,
+};
+ALIAS_MV(wildfire)
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 8edfef27d..7b2f8be03 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -27,30 +27,234 @@ dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
regs->pc, regs->r26, regs->ps);
- printk("r0 = %016lx r1 = %016lx r2 = %016lx\n",
+ printk("v0 = %016lx t0 = %016lx t1 = %016lx\n",
regs->r0, regs->r1, regs->r2);
- printk("r3 = %016lx r4 = %016lx r5 = %016lx\n",
+ printk("t2 = %016lx t3 = %016lx t4 = %016lx\n",
regs->r3, regs->r4, regs->r5);
- printk("r6 = %016lx r7 = %016lx r8 = %016lx\n",
+ printk("t5 = %016lx t6 = %016lx t7 = %016lx\n",
regs->r6, regs->r7, regs->r8);
if (r9_15) {
- printk("r9 = %016lx r10= %016lx r11= %016lx\n",
+ printk("s0 = %016lx s1 = %016lx s2 = %016lx\n",
r9_15[9], r9_15[10], r9_15[11]);
- printk("r12= %016lx r13= %016lx r14= %016lx\n",
+ printk("s3 = %016lx s4 = %016lx s5 = %016lx\n",
r9_15[12], r9_15[13], r9_15[14]);
- printk("r15= %016lx\n", r9_15[15]);
+ printk("s6 = %016lx\n", r9_15[15]);
}
- printk("r16= %016lx r17= %016lx r18= %016lx\n",
+ printk("a0 = %016lx a1 = %016lx a2 = %016lx\n",
regs->r16, regs->r17, regs->r18);
- printk("r19= %016lx r20= %016lx r21= %016lx\n",
+ printk("a3 = %016lx a4 = %016lx a5 = %016lx\n",
regs->r19, regs->r20, regs->r21);
- printk("r22= %016lx r23= %016lx r24= %016lx\n",
+ printk("t8 = %016lx t9 = %016lx t10= %016lx\n",
regs->r22, regs->r23, regs->r24);
- printk("r25= %016lx r27= %016lx r28= %016lx\n",
+ printk("t11= %016lx pv = %016lx at = %016lx\n",
regs->r25, regs->r27, regs->r28);
printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
+#if 0
+__halt();
+#endif
+}
+
+static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+ "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
+ "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
+ "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
+
+static char * inst_name[] = {"call_pal", "", "", "", "", "", "", "",
+ "lda", "ldah", "ldbu", "ldq_u", "ldwu", "stw", "stb", "stq_u",
+ "ALU", "ALU", "ALU", "ALU", "SQRT", "FVAX", "FIEEE", "FLOAT",
+ "MISC", "PAL19", "JMP", "PAL1B", "GRAPH", "PAL1D", "PAL1E", "PAL1F",
+ "ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt",
+ "ldl", "ldq", "ldl_l", "ldq_l", "stl", "stq", "stl_c", "stq_c",
+ "br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt"
+ "blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt"
+};
+
+static char * jump_name[] = {"jmp", "jsr", "ret", "jsr_coroutine"};
+
+typedef struct {int func; char * text;} alist;
+
+static alist inta_name[] = {{0, "addl"}, {2, "s4addl"}, {9, "subl"},
+ {0xb, "s4subl"}, {0xf, "cmpbge"}, {0x12, "s8addl"}, {0x1b, "s8subl"},
+ {0x1d, "cmpult"}, {0x20, "addq"}, {0x22, "s4addq"}, {0x29, "subq"},
+ {0x2b, "s4subq"}, {0x2d, "cmpeq"}, {0x32, "s8addq"}, {0x3b, "s8subq"},
+ {0x3d, "cmpule"}, {0x40, "addl/v"}, {0x49, "subl/v"}, {0x4d, "cmplt"},
+ {0x60, "addq/v"}, {0x69, "subq/v"}, {0x6d, "cmple"}, {-1, 0}};
+
+static alist intl_name[] = {{0, "and"}, {8, "andnot"}, {0x14, "cmovlbs"},
+ {0x16, "cmovlbc"}, {0x20, "or"}, {0x24, "cmoveq"}, {0x26, "cmovne"},
+ {0x28, "ornot"}, {0x40, "xor"}, {0x44, "cmovlt"}, {0x46, "cmovge"},
+ {0x48, "eqv"}, {0x61, "amask"}, {0x64, "cmovle"}, {0x66, "cmovgt"},
+ {0x6c, "implver"}, {-1, 0}};
+
+static alist ints_name[] = {{2, "mskbl"}, {6, "extbl"}, {0xb, "insbl"},
+ {0x12, "mskwl"}, {0x16, "extwl"}, {0x1b, "inswl"}, {0x22, "mskll"},
+ {0x26, "extll"}, {0x2b, "insll"}, {0x30, "zap"}, {0x31, "zapnot"},
+ {0x32, "mskql"}, {0x34, "srl"}, {0x36, "extql"}, {0x39, "sll"},
+ {0x3b, "insql"}, {0x3c, "sra"}, {0x52, "mskwh"}, {0x57, "inswh"},
+ {0x5a, "extwh"}, {0x62, "msklh"}, {0x67, "inslh"}, {0x6a, "extlh"},
+ {0x72, "mskqh"}, {0x77, "insqh"}, {0x7a, "extqh"}, {-1, 0}};
+
+static alist intm_name[] = {{0, "mull"}, {0x20, "mulq"}, {0x30, "umulh"},
+ {0x40, "mull/v"}, {0x60, "mulq/v"}, {-1, 0}};
+
+static alist * int_name[] = {inta_name, intl_name, ints_name, intm_name};
+
+static char *
+assoc(int fcode, alist * a)
+{
+ while ((fcode != a->func) && (a->func != -1))
+ ++a;
+ return a->text;
+}
+
+static char *
+iname(unsigned int instr)
+{
+ int opcode = instr >> 26;
+ char * name = inst_name[opcode];
+
+ switch (opcode) {
+ default:
+ break;
+
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13: {
+ char * specific_name
+ = assoc((instr >> 5) & 0x3f, int_name[opcode - 0x10]);
+ if (specific_name)
+ name = specific_name;
+ break;
+ }
+
+ case 0x1a:
+ name = jump_name[(instr >> 14) & 3];
+ break;
+ }
+
+ return name;
+}
+
+static enum {NOT_INST, PAL, BRANCH, MEMORY, JUMP, OPERATE, FOPERATE, MISC}
+iformat(int opcode)
+{
+ if (opcode >= 0x30)
+ return BRANCH;
+ if (opcode >= 0x20)
+ return MEMORY;
+ if (opcode == 0)
+ return PAL;
+ if (opcode < 8)
+ return NOT_INST;
+ if (opcode < 0x10)
+ return MEMORY;
+ if (opcode < 0x14)
+ return OPERATE;
+ if (opcode < 0x18)
+ return FOPERATE;
+ switch (opcode) {
+ case 0x18:
+ return MISC;
+ case 0x1A:
+ return JUMP;
+ case 0x1C:
+ return OPERATE;
+ default:
+ return NOT_INST;
+ }
+}
+
+/*
+ * The purpose here is to provide useful clues about a kernel crash, so
+ * less likely instructions, e.g. floating point, aren't fully decoded.
+ */
+static void
+disassemble(unsigned int instr)
+{
+ int optype = instr >> 26;
+ char buf[40], *s = buf;
+
+ s += sprintf(buf, "%08x %s ", instr, iname(instr));
+ switch (iformat(optype)) {
+ default:
+ case NOT_INST:
+ case MISC:
+ break;
+
+ case PAL:
+ s += sprintf(s, "%d", instr);
+ break;
+
+ case BRANCH: {
+ int reg = (instr >> 21) & 0x1f;
+ int offset = instr & 0x1fffff;
+
+ if (offset >= 0x100000)
+ offset -= 0x200000;
+ if (((optype & 3) == 0) || (optype >= 0x38)) {
+ if ((optype != 0x30) || (reg != 0x1f))
+ s += sprintf(s, "%s,", ireg_name[reg]);
+ } else
+ s += sprintf(s, "f%d,", reg);
+ s += sprintf(s, ".%+d", (offset + 1) << 2);
+ break;
+ }
+
+ case MEMORY: {
+ int addr_reg = (instr >> 16) & 0x1f;
+ int value_reg = (instr >> 21) & 0x1f;
+ int offset = instr & 0xffff;
+
+ if (offset >= 0x8000)
+ offset -= 0x10000;
+ if ((optype >= 0x20) && (optype < 0x28))
+ s += sprintf(s, "f%d", value_reg);
+ else
+ s += sprintf(s, "%s", ireg_name[value_reg]);
+
+ s += sprintf(s, ",%d(%s)", offset, ireg_name[addr_reg]);
+ break;
+ }
+
+ case JUMP: {
+ int target_reg = (instr >> 16) & 0x1f;
+ int return_reg = (instr >> 21) & 0x1f;
+
+ s += sprintf(s, "%s,", ireg_name[return_reg]);
+ s += sprintf(s, "(%s)", ireg_name[target_reg]);
+ break;
+ }
+
+ case OPERATE: {
+ int areg = (instr >> 21) & 0x1f;
+ int breg = (instr >> 16) & 0x1f;
+ int creg = instr & 0x1f;
+ int litflag = instr & (1<<12);
+ int lit = (instr >> 13) & 0xff;
+
+ s += sprintf(s, "%s,", ireg_name[areg]);
+ if (litflag)
+ s += sprintf(s, "%d", lit);
+ else
+ s += sprintf(s, "%s", ireg_name[breg]);
+ s += sprintf(s, ",%s", ireg_name[creg]);
+ break;
+ }
+
+ case FOPERATE: {
+ int areg = (instr >> 21) & 0x1f;
+ int breg = (instr >> 16) & 0x1f;
+ int creg = instr & 0x1f;
+
+ s += sprintf(s, "f%d,f%d,f%d", areg, breg, creg);
+ break;
+ }
+ }
+ buf[s-buf] = 0;
+ printk("%s\n", buf);
}
static void
@@ -59,11 +263,12 @@ dik_show_code(unsigned int *pc)
long i;
printk("Code:");
- for (i = -3; i < 6; i++) {
+ for (i = -6; i < 2; i++) {
unsigned int insn;
if (__get_user(insn, pc+i))
break;
- printk("%c%08x%c",i?' ':'<',insn,i?' ':'>');
+ printk("%c", i ? ' ' : '*');
+ disassemble(insn);
}
printk("\n");
}
@@ -81,8 +286,12 @@ dik_show_trace(unsigned long *sp)
continue;
if (tmp >= (unsigned long) &_etext)
continue;
- printk(" [<%lx>]", tmp);
- if (++i > 40) {
+ /*
+ * Assume that only the low 24-bits of a kernel text address
+ * is interesting.
+ */
+ printk("%6x%c", (int)tmp & 0xffffff, (++i % 11) ? ' ' : '\n');
+ if (i > 40) {
printk(" ...");
break;
}
@@ -450,7 +659,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
got_exception:
/* Ok, we caught the exception, but we don't want it. Is there
someone to pass it along to? */
- if ((fixup = search_exception_table(pc)) != 0) {
+ if ((fixup = search_exception_table(pc, regs.gp)) != 0) {
unsigned long newpc;
newpc = fixup_exception(una_reg, fixup, pc);
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 52571557b..b6cf88e3d 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -2,13 +2,18 @@
# Makefile for alpha-specific library files..
#
+.S.s:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
checksum.o csum_partial_copy.o strlen.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 fpreg.o \
- srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
+ callback_srm.o callback_init.o srm_puts.o srm_printk.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
diff --git a/arch/alpha/lib/callback_init.c b/arch/alpha/lib/callback_init.c
new file mode 100644
index 000000000..fe643ccfc
--- /dev/null
+++ b/arch/alpha/lib/callback_init.c
@@ -0,0 +1,79 @@
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include <asm/page.h>
+#include <asm/hwrpb.h>
+#include <asm/console.h>
+#include <asm/pgtable.h>
+
+#include "../kernel/proto.h"
+
+extern struct hwrpb_struct *hwrpb;
+
+/* This is the SRM version. Maybe there will be a DBM version. */
+
+int callback_init_done = 0;
+
+void * __init callback_init(void * kernel_end)
+{
+ int i, j;
+ unsigned long vaddr = CONSOLE_REMAP_START;
+ struct crb_struct * crb;
+ pgd_t * pgd = pgd_offset_k(vaddr);
+ pmd_t * pmd;
+ unsigned long two_pte_pages;
+
+ if (!alpha_using_srm) {
+ switch_to_system_map();
+ return kernel_end;
+ }
+
+ /* Allocate some memory for the pages. */
+ two_pte_pages = ((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK;
+ kernel_end = (void *)(two_pte_pages + 2*PAGE_SIZE);
+ memset((void *)two_pte_pages, 0, 2*PAGE_SIZE);
+
+ /* Starting at the HWRPB, locate the CRB. */
+ crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
+
+ /* Tell the console whither the console is to be remapped. */
+ if (srm_fixup(vaddr, (unsigned long)hwrpb))
+ __halt(); /* "We're boned." --Bender */
+
+ /* Edit the procedure descriptors for DISPATCH and FIXUP. */
+ crb->dispatch_va = (struct procdesc_struct *)
+ (vaddr + (unsigned long)crb->dispatch_va - crb->map[0].va);
+ crb->fixup_va = (struct procdesc_struct *)
+ (vaddr + (unsigned long)crb->fixup_va - crb->map[0].va);
+
+ switch_to_system_map();
+
+ /*
+ * Set up the first and second level PTEs for console callbacks.
+ * There is an assumption here that only one of each is needed,
+ * and this allows for 8MB. Currently (late 1999), big consoles
+ * are still under 4MB.
+ */
+ pgd_set(pgd, (pmd_t *)two_pte_pages);
+ pmd = pmd_offset(pgd, vaddr);
+ pmd_set(pmd, (pte_t *)(two_pte_pages + PAGE_SIZE));
+
+ /*
+ * Set up the third level PTEs and update the virtual addresses
+ * of the CRB entries.
+ */
+ for (i = 0; i < crb->map_entries; ++i) {
+ unsigned long paddr = crb->map[i].pa;
+ crb->map[i].va = vaddr;
+ for (j = 0; j < crb->map[i].count; ++j) {
+ set_pte(pte_offset(pmd, vaddr),
+ mk_pte_phys(paddr, PAGE_KERNEL));
+ paddr += PAGE_SIZE;
+ vaddr += PAGE_SIZE;
+ }
+ }
+
+ callback_init_done = 1;
+ return kernel_end;
+}
+
diff --git a/arch/alpha/lib/callback_srm.S b/arch/alpha/lib/callback_srm.S
new file mode 100644
index 000000000..de2edebb1
--- /dev/null
+++ b/arch/alpha/lib/callback_srm.S
@@ -0,0 +1,102 @@
+/*
+ * arch/alpha/lib/callback_srm.S
+ */
+
+#include <linux/config.h>
+#include <asm/console.h>
+
+.text
+#define HWRPB_CRB_OFFSET 0xc0
+
+#if defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC)
+.align 4
+srm_dispatch:
+#if defined(CONFIG_ALPHA_GENERIC)
+ ldl $4,alpha_using_srm
+ beq $4,nosrm
+#endif
+ ldq $0,hwrpb # gp is set up by CALLBACK macro.
+ ldl $25,0($25) # Pick up the wrapper data.
+ mov $20,$21 # Shift arguments right.
+ mov $19,$20
+ ldq $1,HWRPB_CRB_OFFSET($0)
+ mov $18,$19
+ mov $17,$18
+ mov $16,$17
+ addq $0,$1,$2 # CRB address
+ ldq $27,0($2) # DISPATCH procedure descriptor (VMS call std)
+ extwl $25,0,$16 # SRM callback function code
+ ldq $3,8($27) # call address
+ extwl $25,2,$25 # argument information (VMS calling std)
+ jmp ($3) # Return directly to caller of wrapper.
+
+.align 4
+.globl srm_fixup
+.ent srm_fixup
+srm_fixup:
+ ldgp $29,0($27)
+#if defined(CONFIG_ALPHA_GENERIC)
+ ldl $4,alpha_using_srm
+ beq $4,nosrm
+#endif
+ ldq $0,hwrpb
+ ldq $1,HWRPB_CRB_OFFSET($0)
+ addq $0,$1,$2 # CRB address
+ ldq $27,16($2) # VA of FIXUP procedure descriptor
+ ldq $3,8($27) # call address
+ lda $25,2($31) # two integer arguments
+ jmp ($3) # Return directly to caller of srm_fixup.
+.end srm_fixup
+
+#if defined(CONFIG_ALPHA_GENERIC)
+.align 3
+nosrm:
+ lda $0,-1($31)
+ ret
+#endif
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 4; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+ldgp $29,0($27); br $25,srm_dispatch; .word CODE, ARG_CNT; .end callback_##NAME
+
+#else /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 3; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+lda $0,-1($31); ret; .end callback_##NAME
+
+.align 3
+.globl srm_fixup
+.ent srm_fixup
+srm_fixup:
+ lda $0,-1($31)
+ ret
+.end srm_fixup
+#endif /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+CALLBACK(puts, CCB_PUTS, 4)
+CALLBACK(open, CCB_OPEN, 3)
+CALLBACK(close, CCB_CLOSE, 2)
+CALLBACK(read, CCB_READ, 5)
+CALLBACK(getenv, CCB_GET_ENV, 4)
+CALLBACK(setenv, CCB_SET_ENV, 4)
+CALLBACK(getc, CCB_GETC, 2)
+CALLBACK(reset_term, CCB_RESET_TERM, 2)
+CALLBACK(term_int, CCB_SET_TERM_INT, 3)
+CALLBACK(term_ctl, CCB_SET_TERM_CTL, 3)
+CALLBACK(process_keycode, CCB_PROCESS_KEYCODE, 3)
+CALLBACK(ioctl, CCB_IOCTL, 6)
+CALLBACK(write, CCB_WRITE, 5)
+CALLBACK(reset_env, CCB_RESET_ENV, 4)
+CALLBACK(save_env, CCB_SAVE_ENV, 1)
+CALLBACK(pswitch, CCB_PSWITCH, 3)
+CALLBACK(bios_emul, CCB_BIOS_EMUL, 5)
+
+.data
+__alpha_using_srm: # For use by bootpheader
+ .long 7 # value is not 1 for link debugging
+ .weak alpha_using_srm; alpha_using_srm = __alpha_using_srm
+__callback_init_done: # For use by bootpheader
+ .long 7 # value is not 1 for link debugging
+ .weak callback_init_done; callback_init_done = __callback_init_done
+
diff --git a/arch/alpha/lib/srm_dispatch.S b/arch/alpha/lib/srm_dispatch.S
deleted file mode 100644
index 2bcea3073..000000000
--- a/arch/alpha/lib/srm_dispatch.S
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * arch/alpha/lib/srm_dispatch.S
- */
-
-.globl srm_dispatch
-.ent srm_dispatch
-srm_dispatch:
- .frame $30,30,$26
- subq $30,80,$30
- stq $26,0($30)
- stq $8,8($30)
- stq $9,16($30)
- stq $10,24($30)
- stq $11,32($30)
- stq $12,40($30)
- stq $13,48($30)
- stq $14,56($30)
- stq $15,64($30)
- stq $29,72($30)
- .mask 0x2400FF00, -80
- .prologue 0
-
- ldq $1,hwrpb
- ldq $2,0xc0($1) /* crb offset */
- addq $2,$1,$2 /* crb */
- ldq $27,0($2) /* dispatch procedure value */
-
- ldq $2,8($27) /* dispatch call address */
- jsr $26,($2) /* call it (weird VMS call seq) */
-
- ldq $26,0($30)
- ldq $8,8($30)
- ldq $9,16($30)
- ldq $10,24($30)
- ldq $11,32($30)
- ldq $12,40($30)
- ldq $13,48($30)
- ldq $14,56($30)
- ldq $15,64($30)
- ldq $29,72($30)
- addq $30,80,$30
- ret $31,($26),1
-.end srm_dispatch
diff --git a/arch/alpha/lib/srm_fixup.S b/arch/alpha/lib/srm_fixup.S
deleted file mode 100644
index 9cf2d78c2..000000000
--- a/arch/alpha/lib/srm_fixup.S
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/alpha/lib/srm_fixup.S
- */
-
-.globl srm_fixup
-.ent srm_fixup
-srm_fixup:
- .frame $30,30,$26
- subq $30,80,$30
- stq $26,0($30)
- stq $8,8($30)
- stq $9,16($30)
- stq $10,24($30)
- stq $11,32($30)
- stq $12,40($30)
- stq $13,48($30)
- stq $14,56($30)
- stq $15,64($30)
- stq $29,72($30)
- .mask 0x2400FF00, -80
- .prologue 0
-
- ldq $2,0xc0($17) /* crb offset */
- addq $2,$1,$2 /* crb */
- ldq $27,16($2) /* fixup procedure value */
-
- ldq $2,8($27) /* dispatch call address */
- jsr $26,($2) /* call it (weird VMS call seq) */
-
- ldq $26,0($30)
- ldq $8,8($30)
- ldq $9,16($30)
- ldq $10,24($30)
- ldq $11,32($30)
- ldq $12,40($30)
- ldq $13,48($30)
- ldq $14,56($30)
- ldq $15,64($30)
- ldq $29,72($30)
- addq $30,80,$30
- ret $31,($26),1
-.end srm_fixup
diff --git a/arch/alpha/lib/srm_printk.c b/arch/alpha/lib/srm_printk.c
index b5baee15f..31b53c494 100644
--- a/arch/alpha/lib/srm_printk.c
+++ b/arch/alpha/lib/srm_printk.c
@@ -9,13 +9,33 @@ long
srm_printk(const char *fmt, ...)
{
static char buf[1024];
- va_list args;
- long i;
+ va_list args;
+ long len, num_lf;
+ char *src, *dst;
- va_start(args, fmt);
- i = vsprintf(buf,fmt,args);
- va_end(args);
+ va_start(args, fmt);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
- srm_puts(buf);
- return i;
+ /* count number of linefeeds in string: */
+
+ num_lf = 0;
+ for (src = buf; *src; ++src) {
+ if (*src == '\n') {
+ ++num_lf;
+ }
+ }
+
+ if (num_lf) {
+ /* expand each linefeed into carriage-return/linefeed: */
+ for (dst = src + num_lf; src >= buf; ) {
+ if (*src == '\n') {
+ *dst-- = '\r';
+ }
+ *dst-- = *src--;
+ }
+ }
+
+ srm_puts(buf, num_lf+len);
+ return len;
}
diff --git a/arch/alpha/lib/srm_puts.c b/arch/alpha/lib/srm_puts.c
index 87b1d1155..7b60a6f75 100644
--- a/arch/alpha/lib/srm_puts.c
+++ b/arch/alpha/lib/srm_puts.c
@@ -5,30 +5,19 @@
#include <linux/string.h>
#include <asm/console.h>
-void
-srm_puts(const char *str)
+long
+srm_puts(const char *str, long len)
{
- /* Expand \n to \r\n as we go. */
+ long remaining, written;
- while (*str) {
- long len;
- const char *e = str;
+ if (!callback_init_done)
+ return len;
- if (*str == '\n') {
- if (srm_dispatch(CCB_PUTS, 0, "\r", 1) < 0)
- return;
- ++e;
- }
-
- e = strchr(e, '\n') ? : strchr(e, '\0');
- len = e - str;
-
- while (len > 0) {
- long written = srm_dispatch(CCB_PUTS, 0, str, len);
- if (written < 0)
- return;
- len -= written & 0xffffffff;
- str += written & 0xffffffff;
- }
+ for (remaining = len; remaining > 0; remaining -= written)
+ {
+ written = callback_puts(0, str, remaining);
+ written &= 0xffffffff;
+ str += written;
}
+ return len;
}
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c
index 12a1f4803..d3a02fe27 100644
--- a/arch/alpha/mm/extable.c
+++ b/arch/alpha/mm/extable.c
@@ -36,12 +36,12 @@ search_one_table(const struct exception_table_entry *first,
register unsigned long gp __asm__("$29");
-unsigned
-search_exception_table(unsigned long addr)
+static unsigned
+search_exception_table_without_gp(unsigned long addr)
{
unsigned ret;
-#ifndef CONFIG_MODULE
+#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table - 1,
addr - gp);
@@ -60,3 +60,39 @@ search_exception_table(unsigned long addr)
return 0;
}
+
+unsigned
+search_exception_table(unsigned long addr, unsigned long exc_gp)
+{
+ unsigned ret;
+
+#ifndef CONFIG_MODULES
+ ret = search_one_table(__start___ex_table, __stop___ex_table - 1,
+ addr - exc_gp);
+ if (ret) return ret;
+#else
+ /* The kernel is the last "module" -- no need to treat it special. */
+ struct module *mp;
+ for (mp = module_list; mp ; mp = mp->next) {
+ if (!mp->ex_table_start)
+ continue;
+ ret = search_one_table(mp->ex_table_start,
+ mp->ex_table_end - 1, addr - exc_gp);
+ if (ret) return ret;
+ }
+#endif
+
+ /*
+ * The search failed with the exception gp. To be safe, try the
+ * old method before giving up.
+ */
+ ret = search_exception_table_without_gp(addr);
+ if (ret) {
+ printk(KERN_ALERT, "%s: [%lx] EX_TABLE search fail with"
+ "exc frame GP, success with raw GP\n",
+ current->comm, addr);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 1639972db..bf4839b8f 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -164,11 +164,13 @@ bad_area:
no_context:
/* Are we prepared to handle this fault as an exception? */
- if ((fixup = search_exception_table(regs->pc)) != 0) {
+ if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) {
unsigned long newpc;
newpc = fixup_exception(dpf_reg, fixup, regs->pc);
- printk("%s: Exception at [<%lx>] (%lx)\n",
+#if 1
+ printk("%s: Exception at [<%lx>] (%lx) handled successfully\n",
current->comm, regs->pc, newpc);
+#endif
regs->pc = newpc;
return;
}
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 2cbe9bb0f..84b608f45 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -182,43 +182,15 @@ load_PCB(struct thread_struct * pcb)
return __reload_thread(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).
- */
+/* switch_to_system_map() sets up some necessary page tables. */
void
-paging_init(void)
+switch_to_system_map(void)
{
unsigned long newptbr;
unsigned long original_pcb_ptr;
- unsigned long 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
-
- 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_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]) =
@@ -253,6 +225,41 @@ paging_init(void)
original_pcb = *(struct thread_struct *) original_pcb_ptr;
}
+/*
+ * paging_init() sets up the memory map.
+ */
+void
+paging_init(void)
+{
+ unsigned long 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 (~((1L << (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
+
+ 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 ZERO_PGE. */
+ memset((void *)ZERO_PGE, 0, PAGE_SIZE);
+}
+
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
void
srm_paging_stop (void)
diff --git a/arch/alpha/vmlinux.lds b/arch/alpha/vmlinux.lds
index 4eaac4e42..f64a926b6 100644
--- a/arch/alpha/vmlinux.lds
+++ b/arch/alpha/vmlinux.lds
@@ -2,7 +2,7 @@ OUTPUT_FORMAT("elf64-alpha")
ENTRY(__start)
SECTIONS
{
- . = 0xfffffc0000310000;
+ . = 0xfffffc0000810000;
_text = .;
.text : { *(.text) }
_etext = .;
@@ -50,9 +50,11 @@ SECTIONS
.got : { *(.got) }
.sdata : { *(.sdata) }
_edata = .;
- _bss = .;
+
+ __bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss : { *(.bss) *(COMMON) }
+ __bss_stop = .;
_end = .;
.mdebug 0 : { *(.mdebug) }