aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-11 15:22:18 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-11 15:22:18 -0400
commit6c82a000a29b93541b5b7db597a083c069755cc9 (patch)
treeb9e49724f56b47e4b3d0bd6c6fa3be88dac3a9e6 /arch
parent5b4d2386c23e5de553fce002892c7691a989b350 (diff)
parent39415a440ecceb0a5bd3c23686f18f83bb8368c6 (diff)
Merge branch 'x86/generalize-visws' into x86/core
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/Kconfig62
-rw-r--r--arch/x86/Makefile4
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/apic_32.c2
-rw-r--r--arch/x86/kernel/e820.c11
-rw-r--r--arch/x86/kernel/mpparse.c20
-rw-r--r--arch/x86/kernel/setup.c1
-rw-r--r--arch/x86/kernel/visws_quirks.c709
-rw-r--r--arch/x86/lguest/Kconfig2
-rw-r--r--arch/x86/mach-default/setup.c32
-rw-r--r--arch/x86/mach-visws/Makefile8
-rw-r--r--arch/x86/mach-visws/mpparse.c85
-rw-r--r--arch/x86/mach-visws/reboot.c55
-rw-r--r--arch/x86/mach-visws/setup.c183
-rw-r--r--arch/x86/mach-visws/traps.c69
-rw-r--r--arch/x86/mach-visws/visws_apic.c296
-rw-r--r--arch/x86/pci/Makefile4
-rw-r--r--arch/x86/pci/legacy.c5
-rw-r--r--arch/x86/pci/numa.c10
-rw-r--r--arch/x86/pci/pci.h1
-rw-r--r--arch/x86/pci/visws.c19
21 files changed, 826 insertions, 753 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3b1b1da78dae..2cfccc987a26 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -181,12 +181,12 @@ config X86_64_SMP
181config X86_HT 181config X86_HT
182 bool 182 bool
183 depends on SMP 183 depends on SMP
184 depends on (X86_32 && !(X86_VISWS || X86_VOYAGER)) || X86_64 184 depends on (X86_32 && !X86_VOYAGER) || X86_64
185 default y 185 default y
186 186
187config X86_BIOS_REBOOT 187config X86_BIOS_REBOOT
188 bool 188 bool
189 depends on !X86_VISWS && !X86_VOYAGER 189 depends on !X86_VOYAGER
190 default y 190 default y
191 191
192config X86_TRAMPOLINE 192config X86_TRAMPOLINE
@@ -232,13 +232,13 @@ config SMP
232 232
233config X86_FIND_SMP_CONFIG 233config X86_FIND_SMP_CONFIG
234 def_bool y 234 def_bool y
235 depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS 235 depends on X86_MPPARSE || X86_VOYAGER
236 236
237if ACPI 237if ACPI
238config X86_MPPARSE 238config X86_MPPARSE
239 def_bool y 239 def_bool y
240 bool "Enable MPS table" 240 bool "Enable MPS table"
241 depends on X86_LOCAL_APIC && !X86_VISWS 241 depends on X86_LOCAL_APIC
242 help 242 help
243 For old smp systems that do not have proper acpi support. Newer systems 243 For old smp systems that do not have proper acpi support. Newer systems
244 (esp with 64bit cpus) with acpi support, MADT and DSDT will override it 244 (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
@@ -247,7 +247,7 @@ endif
247if !ACPI 247if !ACPI
248config X86_MPPARSE 248config X86_MPPARSE
249 def_bool y 249 def_bool y
250 depends on X86_LOCAL_APIC && !X86_VISWS 250 depends on X86_LOCAL_APIC
251endif 251endif
252 252
253choice 253choice
@@ -281,18 +281,6 @@ config X86_VOYAGER
281 If you do not specifically know you have a Voyager based machine, 281 If you do not specifically know you have a Voyager based machine,
282 say N here, otherwise the kernel you build will not be bootable. 282 say N here, otherwise the kernel you build will not be bootable.
283 283
284config X86_VISWS
285 bool "SGI 320/540 (Visual Workstation)"
286 depends on X86_32 && PCI
287 help
288 The SGI Visual Workstation series is an IA32-based workstation
289 based on SGI systems chips with some legacy PC hardware attached.
290
291 Say Y here to create a kernel to run on the SGI 320 or 540.
292
293 A kernel compiled for the Visual Workstation will not run on PCs
294 and vice versa. See <file:Documentation/sgi-visws.txt> for details.
295
296config X86_GENERICARCH 284config X86_GENERICARCH
297 bool "Generic architecture" 285 bool "Generic architecture"
298 depends on X86_32 286 depends on X86_32
@@ -363,6 +351,18 @@ config X86_VSMP
363 351
364endchoice 352endchoice
365 353
354config X86_VISWS
355 bool "SGI 320/540 (Visual Workstation)"
356 depends on X86_32 && PCI && !X86_VOYAGER && X86_MPPARSE && PCI_GODIRECT
357 help
358 The SGI Visual Workstation series is an IA32-based workstation
359 based on SGI systems chips with some legacy PC hardware attached.
360
361 Say Y here to create a kernel to run on the SGI 320 or 540.
362
363 A kernel compiled for the Visual Workstation will run on general
364 PCs as well. See <file:Documentation/sgi-visws.txt> for details.
365
366config SCHED_NO_NO_OMIT_FRAME_POINTER 366config SCHED_NO_NO_OMIT_FRAME_POINTER
367 def_bool y 367 def_bool y
368 prompt "Single-depth WCHAN output" 368 prompt "Single-depth WCHAN output"
@@ -391,7 +391,7 @@ config VMI
391 bool "VMI Guest support" 391 bool "VMI Guest support"
392 select PARAVIRT 392 select PARAVIRT
393 depends on X86_32 393 depends on X86_32
394 depends on !(X86_VISWS || X86_VOYAGER) 394 depends on !X86_VOYAGER
395 help 395 help
396 VMI provides a paravirtualized interface to the VMware ESX server 396 VMI provides a paravirtualized interface to the VMware ESX server
397 (it could be used by other hypervisors in theory too, but is not 397 (it could be used by other hypervisors in theory too, but is not
@@ -402,7 +402,7 @@ config KVM_CLOCK
402 bool "KVM paravirtualized clock" 402 bool "KVM paravirtualized clock"
403 select PARAVIRT 403 select PARAVIRT
404 select PARAVIRT_CLOCK 404 select PARAVIRT_CLOCK
405 depends on !(X86_VISWS || X86_VOYAGER) 405 depends on !X86_VOYAGER
406 help 406 help
407 Turning on this option will allow you to run a paravirtualized clock 407 Turning on this option will allow you to run a paravirtualized clock
408 when running over the KVM hypervisor. Instead of relying on a PIT 408 when running over the KVM hypervisor. Instead of relying on a PIT
@@ -413,7 +413,7 @@ config KVM_CLOCK
413config KVM_GUEST 413config KVM_GUEST
414 bool "KVM Guest support" 414 bool "KVM Guest support"
415 select PARAVIRT 415 select PARAVIRT
416 depends on !(X86_VISWS || X86_VOYAGER) 416 depends on !X86_VOYAGER
417 help 417 help
418 This option enables various optimizations for running under the KVM 418 This option enables various optimizations for running under the KVM
419 hypervisor. 419 hypervisor.
@@ -422,7 +422,7 @@ source "arch/x86/lguest/Kconfig"
422 422
423config PARAVIRT 423config PARAVIRT
424 bool "Enable paravirtualization code" 424 bool "Enable paravirtualization code"
425 depends on !(X86_VISWS || X86_VOYAGER) 425 depends on !X86_VOYAGER
426 help 426 help
427 This changes the kernel so it can modify itself when it is run 427 This changes the kernel so it can modify itself when it is run
428 under a hypervisor, potentially improving performance significantly 428 under a hypervisor, potentially improving performance significantly
@@ -628,7 +628,7 @@ source "kernel/Kconfig.preempt"
628 628
629config X86_UP_APIC 629config X86_UP_APIC
630 bool "Local APIC support on uniprocessors" 630 bool "Local APIC support on uniprocessors"
631 depends on X86_32 && !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH) 631 depends on X86_32 && !SMP && !(X86_VOYAGER || X86_GENERICARCH)
632 help 632 help
633 A local APIC (Advanced Programmable Interrupt Controller) is an 633 A local APIC (Advanced Programmable Interrupt Controller) is an
634 integrated interrupt controller in the CPU. If you have a single-CPU 634 integrated interrupt controller in the CPU. If you have a single-CPU
@@ -653,11 +653,11 @@ config X86_UP_IOAPIC
653 653
654config X86_LOCAL_APIC 654config X86_LOCAL_APIC
655 def_bool y 655 def_bool y
656 depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH)) 656 depends on X86_64 || (X86_32 && (X86_UP_APIC || (SMP && !X86_VOYAGER) || X86_GENERICARCH))
657 657
658config X86_IO_APIC 658config X86_IO_APIC
659 def_bool y 659 def_bool y
660 depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH)) 660 depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !X86_VOYAGER) || X86_GENERICARCH))
661 661
662config X86_VISWS_APIC 662config X86_VISWS_APIC
663 def_bool y 663 def_bool y
@@ -711,7 +711,7 @@ config X86_MCE_NONFATAL
711 711
712config X86_MCE_P4THERMAL 712config X86_MCE_P4THERMAL
713 bool "check for P4 thermal throttling interrupt." 713 bool "check for P4 thermal throttling interrupt."
714 depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS 714 depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP)
715 help 715 help
716 Enabling this feature will cause a message to be printed when the P4 716 Enabling this feature will cause a message to be printed when the P4
717 enters thermal throttling. 717 enters thermal throttling.
@@ -1414,7 +1414,7 @@ config X86_APM_BOOT
1414 1414
1415menuconfig APM 1415menuconfig APM
1416 tristate "APM (Advanced Power Management) BIOS support" 1416 tristate "APM (Advanced Power Management) BIOS support"
1417 depends on X86_32 && PM_SLEEP && !X86_VISWS 1417 depends on X86_32 && PM_SLEEP
1418 ---help--- 1418 ---help---
1419 APM is a BIOS specification for saving power using several different 1419 APM is a BIOS specification for saving power using several different
1420 techniques. This is mostly useful for battery powered laptops with 1420 techniques. This is mostly useful for battery powered laptops with
@@ -1561,7 +1561,7 @@ config PCI
1561 1561
1562choice 1562choice
1563 prompt "PCI access mode" 1563 prompt "PCI access mode"
1564 depends on X86_32 && PCI && !X86_VISWS 1564 depends on X86_32 && PCI
1565 default PCI_GOANY 1565 default PCI_GOANY
1566 ---help--- 1566 ---help---
1567 On PCI systems, the BIOS can be used to detect the PCI devices and 1567 On PCI systems, the BIOS can be used to detect the PCI devices and
@@ -1598,12 +1598,12 @@ endchoice
1598 1598
1599config PCI_BIOS 1599config PCI_BIOS
1600 def_bool y 1600 def_bool y
1601 depends on X86_32 && !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY) 1601 depends on X86_32 && PCI && (PCI_GOBIOS || PCI_GOANY)
1602 1602
1603# x86-64 doesn't support PCI BIOS access from long mode so always go direct. 1603# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
1604config PCI_DIRECT 1604config PCI_DIRECT
1605 def_bool y 1605 def_bool y
1606 depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS) 1606 depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC))
1607 1607
1608config PCI_MMCONFIG 1608config PCI_MMCONFIG
1609 def_bool y 1609 def_bool y
@@ -1663,7 +1663,7 @@ if X86_32
1663 1663
1664config ISA 1664config ISA
1665 bool "ISA support" 1665 bool "ISA support"
1666 depends on !(X86_VOYAGER || X86_VISWS) 1666 depends on !X86_VOYAGER
1667 help 1667 help
1668 Find out whether you have ISA slots on your motherboard. ISA is the 1668 Find out whether you have ISA slots on your motherboard. ISA is the
1669 name of a bus system, i.e. the way the CPU talks to the other stuff 1669 name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -1690,7 +1690,7 @@ config EISA
1690source "drivers/eisa/Kconfig" 1690source "drivers/eisa/Kconfig"
1691 1691
1692config MCA 1692config MCA
1693 bool "MCA support" if !(X86_VISWS || X86_VOYAGER) 1693 bool "MCA support" if !X86_VOYAGER
1694 default y if X86_VOYAGER 1694 default y if X86_VOYAGER
1695 help 1695 help
1696 MicroChannel Architecture is found in some IBM PS/2 machines and 1696 MicroChannel Architecture is found in some IBM PS/2 machines and
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index b03d24b44bf9..919ce21ea654 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -113,10 +113,6 @@ mcore-y := arch/x86/mach-default/
113mflags-$(CONFIG_X86_VOYAGER) := -Iinclude/asm-x86/mach-voyager 113mflags-$(CONFIG_X86_VOYAGER) := -Iinclude/asm-x86/mach-voyager
114mcore-$(CONFIG_X86_VOYAGER) := arch/x86/mach-voyager/ 114mcore-$(CONFIG_X86_VOYAGER) := arch/x86/mach-voyager/
115 115
116# VISWS subarch support
117mflags-$(CONFIG_X86_VISWS) := -Iinclude/asm-x86/mach-visws
118mcore-$(CONFIG_X86_VISWS) := arch/x86/mach-visws/
119
120# generic subarchitecture 116# generic subarchitecture
121mflags-$(CONFIG_X86_GENERICARCH):= -Iinclude/asm-x86/mach-generic 117mflags-$(CONFIG_X86_GENERICARCH):= -Iinclude/asm-x86/mach-generic
122fcore-$(CONFIG_X86_GENERICARCH) += arch/x86/mach-generic/ 118fcore-$(CONFIG_X86_GENERICARCH) += arch/x86/mach-generic/
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 4033d8dc745b..55ff016e9f69 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -19,6 +19,7 @@ obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
19obj-y += traps_$(BITS).o irq_$(BITS).o 19obj-y += traps_$(BITS).o irq_$(BITS).o
20obj-y += time_$(BITS).o ioport.o ldt.o 20obj-y += time_$(BITS).o ioport.o ldt.o
21obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o 21obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o
22obj-$(CONFIG_X86_VISWS) += visws_quirks.o
22obj-$(CONFIG_X86_32) += probe_roms_32.o 23obj-$(CONFIG_X86_32) += probe_roms_32.o
23obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o 24obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
24obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o 25obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index 3e947208b9d9..3e58b676d23b 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -974,7 +974,7 @@ void __cpuinit setup_local_APIC(void)
974 * Double-check whether this APIC is really registered. 974 * Double-check whether this APIC is really registered.
975 */ 975 */
976 if (!apic_id_registered()) 976 if (!apic_id_registered())
977 BUG(); 977 WARN_ON_ONCE(1);
978 978
979 /* 979 /*
980 * Intel recommends to set DFR, LDR and TPR before enabling 980 * Intel recommends to set DFR, LDR and TPR before enabling
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 9f5002e0b35c..a5383ae2cbe3 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -1313,6 +1313,11 @@ void __init e820_reserve_resources(void)
1313 } 1313 }
1314} 1314}
1315 1315
1316/*
1317 * Non-standard memory setup can be specified via this quirk:
1318 */
1319char * (*arch_memory_setup_quirk)(void);
1320
1316char *__init default_machine_specific_memory_setup(void) 1321char *__init default_machine_specific_memory_setup(void)
1317{ 1322{
1318 char *who = "BIOS-e820"; 1323 char *who = "BIOS-e820";
@@ -1353,6 +1358,12 @@ char *__init default_machine_specific_memory_setup(void)
1353 1358
1354char *__init __attribute__((weak)) machine_specific_memory_setup(void) 1359char *__init __attribute__((weak)) machine_specific_memory_setup(void)
1355{ 1360{
1361 if (arch_memory_setup_quirk) {
1362 char *who = arch_memory_setup_quirk();
1363
1364 if (who)
1365 return who;
1366 }
1356 return default_machine_specific_memory_setup(); 1367 return default_machine_specific_memory_setup();
1357} 1368}
1358 1369
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 8b6b1e05c306..3b25e49380c6 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -726,12 +726,22 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
726static struct intel_mp_floating *mpf_found; 726static struct intel_mp_floating *mpf_found;
727 727
728/* 728/*
729 * Machine specific quirk for finding the SMP config before other setup
730 * activities destroy the table:
731 */
732int (*mach_get_smp_config_quirk)(unsigned int early);
733
734/*
729 * Scan the memory blocks for an SMP configuration block. 735 * Scan the memory blocks for an SMP configuration block.
730 */ 736 */
731static void __init __get_smp_config(unsigned early) 737static void __init __get_smp_config(unsigned int early)
732{ 738{
733 struct intel_mp_floating *mpf = mpf_found; 739 struct intel_mp_floating *mpf = mpf_found;
734 740
741 if (mach_get_smp_config_quirk) {
742 if (mach_get_smp_config_quirk(early))
743 return;
744 }
735 if (acpi_lapic && early) 745 if (acpi_lapic && early)
736 return; 746 return;
737 /* 747 /*
@@ -889,10 +899,16 @@ static int __init smp_scan_config(unsigned long base, unsigned long length,
889 return 0; 899 return 0;
890} 900}
891 901
892static void __init __find_smp_config(unsigned reserve) 902int (*mach_find_smp_config_quirk)(unsigned int reserve);
903
904static void __init __find_smp_config(unsigned int reserve)
893{ 905{
894 unsigned int address; 906 unsigned int address;
895 907
908 if (mach_find_smp_config_quirk) {
909 if (mach_find_smp_config_quirk(reserve))
910 return;
911 }
896 /* 912 /*
897 * FIXME: Linux assumes you have 640K of base ram.. 913 * FIXME: Linux assumes you have 640K of base ram..
898 * this continues the error... 914 * this continues the error...
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 86fc2d624270..987b6fde3a99 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -596,6 +596,7 @@ void __init setup_arch(char **cmdline_p)
596{ 596{
597#ifdef CONFIG_X86_32 597#ifdef CONFIG_X86_32
598 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); 598 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
599 visws_early_detect();
599 pre_setup_arch_hook(); 600 pre_setup_arch_hook();
600 early_cpu_init(); 601 early_cpu_init();
601#else 602#else
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
new file mode 100644
index 000000000000..e94bdb6add1d
--- /dev/null
+++ b/arch/x86/kernel/visws_quirks.c
@@ -0,0 +1,709 @@
1/*
2 * SGI Visual Workstation support and quirks, unmaintained.
3 *
4 * Split out from setup.c by davej@suse.de
5 *
6 * Copyright (C) 1999 Bent Hagemark, Ingo Molnar
7 *
8 * SGI Visual Workstation interrupt controller
9 *
10 * The Cobalt system ASIC in the Visual Workstation contains a "Cobalt" APIC
11 * which serves as the main interrupt controller in the system. Non-legacy
12 * hardware in the system uses this controller directly. Legacy devices
13 * are connected to the PIIX4 which in turn has its 8259(s) connected to
14 * a of the Cobalt APIC entry.
15 *
16 * 09/02/2000 - Updated for 2.4 by jbarnes@sgi.com
17 *
18 * 25/11/2002 - Updated for 2.5 by Andrey Panin <pazke@orbita1.ru>
19 */
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/smp.h>
24
25#include <asm/visws/cobalt.h>
26#include <asm/visws/piix4.h>
27#include <asm/arch_hooks.h>
28#include <asm/fixmap.h>
29#include <asm/reboot.h>
30#include <asm/setup.h>
31#include <asm/e820.h>
32#include <asm/smp.h>
33#include <asm/io.h>
34
35#include <mach_ipi.h>
36
37#include "mach_apic.h"
38
39#include <linux/init.h>
40#include <linux/smp.h>
41
42#include <linux/kernel_stat.h>
43#include <linux/interrupt.h>
44#include <linux/init.h>
45
46#include <asm/io.h>
47#include <asm/apic.h>
48#include <asm/i8259.h>
49#include <asm/irq_vectors.h>
50#include <asm/visws/cobalt.h>
51#include <asm/visws/lithium.h>
52#include <asm/visws/piix4.h>
53
54#include <linux/sched.h>
55#include <linux/kernel.h>
56#include <linux/init.h>
57#include <linux/pci.h>
58#include <linux/pci_ids.h>
59
60extern int no_broadcast;
61
62#include <asm/io.h>
63#include <asm/apic.h>
64#include <asm/arch_hooks.h>
65#include <asm/visws/cobalt.h>
66#include <asm/visws/lithium.h>
67
68char visws_board_type = -1;
69char visws_board_rev = -1;
70
71int is_visws_box(void)
72{
73 return visws_board_type >= 0;
74}
75
76static int __init visws_time_init_quirk(void)
77{
78 printk(KERN_INFO "Starting Cobalt Timer system clock\n");
79
80 /* Set the countdown value */
81 co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
82
83 /* Start the timer */
84 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
85
86 /* Enable (unmask) the timer interrupt */
87 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
88
89 /*
90 * Zero return means the generic timer setup code will set up
91 * the standard vector:
92 */
93 return 0;
94}
95
96static int __init visws_pre_intr_init_quirk(void)
97{
98 init_VISWS_APIC_irqs();
99
100 /*
101 * We dont want ISA irqs to be set up by the generic code:
102 */
103 return 1;
104}
105
106/* Quirk for machine specific memory setup. */
107
108#define MB (1024 * 1024)
109
110unsigned long sgivwfb_mem_phys;
111unsigned long sgivwfb_mem_size;
112EXPORT_SYMBOL(sgivwfb_mem_phys);
113EXPORT_SYMBOL(sgivwfb_mem_size);
114
115long long mem_size __initdata = 0;
116
117static char * __init visws_memory_setup_quirk(void)
118{
119 long long gfx_mem_size = 8 * MB;
120
121 mem_size = boot_params.alt_mem_k;
122
123 if (!mem_size) {
124 printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
125 mem_size = 128 * MB;
126 }
127
128 /*
129 * this hardcodes the graphics memory to 8 MB
130 * it really should be sized dynamically (or at least
131 * set as a boot param)
132 */
133 if (!sgivwfb_mem_size) {
134 printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
135 sgivwfb_mem_size = 8 * MB;
136 }
137
138 /*
139 * Trim to nearest MB
140 */
141 sgivwfb_mem_size &= ~((1 << 20) - 1);
142 sgivwfb_mem_phys = mem_size - gfx_mem_size;
143
144 e820_add_region(0, LOWMEMSIZE(), E820_RAM);
145 e820_add_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
146 e820_add_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);
147
148 return "PROM";
149}
150
151static void visws_machine_emergency_restart(void)
152{
153 /*
154 * Visual Workstations restart after this
155 * register is poked on the PIIX4
156 */
157 outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT);
158}
159
160static void visws_machine_power_off(void)
161{
162 unsigned short pm_status;
163/* extern unsigned int pci_bus0; */
164
165 while ((pm_status = inw(PMSTS_PORT)) & 0x100)
166 outw(pm_status, PMSTS_PORT);
167
168 outw(PM_SUSPEND_ENABLE, PMCNTRL_PORT);
169
170 mdelay(10);
171
172#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
173 (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
174
175/* outl(PCI_CONF1_ADDRESS(pci_bus0, SPECIAL_DEV, SPECIAL_REG), 0xCF8); */
176 outl(PIIX_SPECIAL_STOP, 0xCFC);
177}
178
179static int __init visws_get_smp_config_quirk(unsigned int early)
180{
181 /*
182 * Prevent MP-table parsing by the generic code:
183 */
184 return 1;
185}
186
187extern unsigned int __cpuinitdata maxcpus;
188
189/*
190 * The Visual Workstation is Intel MP compliant in the hardware
191 * sense, but it doesn't have a BIOS(-configuration table).
192 * No problem for Linux.
193 */
194
195static void __init MP_processor_info (struct mpc_config_processor *m)
196{
197 int ver, logical_apicid;
198 physid_mask_t apic_cpus;
199
200 if (!(m->mpc_cpuflag & CPU_ENABLED))
201 return;
202
203 logical_apicid = m->mpc_apicid;
204 printk(KERN_INFO "%sCPU #%d %u:%u APIC version %d\n",
205 m->mpc_cpuflag & CPU_BOOTPROCESSOR ? "Bootup " : "",
206 m->mpc_apicid,
207 (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
208 (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
209 m->mpc_apicver);
210
211 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR)
212 boot_cpu_physical_apicid = m->mpc_apicid;
213
214 ver = m->mpc_apicver;
215 if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) {
216 printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
217 m->mpc_apicid, MAX_APICS);
218 return;
219 }
220
221 apic_cpus = apicid_to_cpu_present(m->mpc_apicid);
222 physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus);
223 /*
224 * Validate version
225 */
226 if (ver == 0x0) {
227 printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! "
228 "fixing up to 0x10. (tell your hw vendor)\n",
229 m->mpc_apicid);
230 ver = 0x10;
231 }
232 apic_version[m->mpc_apicid] = ver;
233}
234
235int __init visws_find_smp_config_quirk(unsigned int reserve)
236{
237 struct mpc_config_processor *mp = phys_to_virt(CO_CPU_TAB_PHYS);
238 unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS));
239
240 if (ncpus > CO_CPU_MAX) {
241 printk(KERN_WARNING "find_visws_smp: got cpu count of %d at %p\n",
242 ncpus, mp);
243
244 ncpus = CO_CPU_MAX;
245 }
246
247 if (ncpus > maxcpus)
248 ncpus = maxcpus;
249
250#ifdef CONFIG_X86_LOCAL_APIC
251 smp_found_config = 1;
252#endif
253 while (ncpus--)
254 MP_processor_info(mp++);
255
256 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
257
258 return 1;
259}
260
261extern int visws_trap_init_quirk(void);
262
263void __init visws_early_detect(void)
264{
265 int raw;
266
267 visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
268 >> PIIX_GPI_BD_SHIFT;
269
270 if (visws_board_type < 0)
271 return;
272
273 /*
274 * Install special quirks for timer, interrupt and memory setup:
275 */
276 arch_time_init_quirk = visws_time_init_quirk;
277 arch_pre_intr_init_quirk = visws_pre_intr_init_quirk;
278 arch_memory_setup_quirk = visws_memory_setup_quirk;
279
280 /*
281 * Fall back to generic behavior for traps:
282 */
283 arch_intr_init_quirk = NULL;
284 arch_trap_init_quirk = visws_trap_init_quirk;
285
286 /*
287 * Install reboot quirks:
288 */
289 pm_power_off = visws_machine_power_off;
290 machine_ops.emergency_restart = visws_machine_emergency_restart;
291
292 /*
293 * Do not use broadcast IPIs:
294 */
295 no_broadcast = 0;
296
297 /*
298 * Override generic MP-table parsing:
299 */
300 mach_get_smp_config_quirk = visws_get_smp_config_quirk;
301 mach_find_smp_config_quirk = visws_find_smp_config_quirk;
302
303#ifdef CONFIG_X86_IO_APIC
304 /*
305 * Turn off IO-APIC detection and initialization:
306 */
307 skip_ioapic_setup = 1;
308#endif
309
310 /*
311 * Get Board rev.
312 * First, we have to initialize the 307 part to allow us access
313 * to the GPIO registers. Let's map them at 0x0fc0 which is right
314 * after the PIIX4 PM section.
315 */
316 outb_p(SIO_DEV_SEL, SIO_INDEX);
317 outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
318
319 outb_p(SIO_DEV_MSB, SIO_INDEX);
320 outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
321
322 outb_p(SIO_DEV_LSB, SIO_INDEX);
323 outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
324
325 outb_p(SIO_DEV_ENB, SIO_INDEX);
326 outb_p(1, SIO_DATA); /* Enable GPIO registers. */
327
328 /*
329 * Now, we have to map the power management section to write
330 * a bit which enables access to the GPIO registers.
331 * What lunatic came up with this shit?
332 */
333 outb_p(SIO_DEV_SEL, SIO_INDEX);
334 outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
335
336 outb_p(SIO_DEV_MSB, SIO_INDEX);
337 outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */
338
339 outb_p(SIO_DEV_LSB, SIO_INDEX);
340 outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */
341
342 outb_p(SIO_DEV_ENB, SIO_INDEX);
343 outb_p(1, SIO_DATA); /* Enable PM registers. */
344
345 /*
346 * Now, write the PM register which enables the GPIO registers.
347 */
348 outb_p(SIO_PM_FER2, SIO_PM_INDEX);
349 outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
350
351 /*
352 * Now, initialize the GPIO registers.
353 * We want them all to be inputs which is the
354 * power on default, so let's leave them alone.
355 * So, let's just read the board rev!
356 */
357 raw = inb_p(SIO_GP_DATA1);
358 raw &= 0x7f; /* 7 bits of valid board revision ID. */
359
360 if (visws_board_type == VISWS_320) {
361 if (raw < 0x6) {
362 visws_board_rev = 4;
363 } else if (raw < 0xc) {
364 visws_board_rev = 5;
365 } else {
366 visws_board_rev = 6;
367 }
368 } else if (visws_board_type == VISWS_540) {
369 visws_board_rev = 2;
370 } else {
371 visws_board_rev = raw;
372 }
373
374 printk(KERN_INFO "Silicon Graphics Visual Workstation %s (rev %d) detected\n",
375 (visws_board_type == VISWS_320 ? "320" :
376 (visws_board_type == VISWS_540 ? "540" :
377 "unknown")), visws_board_rev);
378}
379
380#define A01234 (LI_INTA_0 | LI_INTA_1 | LI_INTA_2 | LI_INTA_3 | LI_INTA_4)
381#define BCD (LI_INTB | LI_INTC | LI_INTD)
382#define ALLDEVS (A01234 | BCD)
383
384static __init void lithium_init(void)
385{
386 set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
387 set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
388
389 if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
390 (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
391 printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A');
392/* panic("This machine is not SGI Visual Workstation 320/540"); */
393 }
394
395 if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
396 (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
397 printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B');
398/* panic("This machine is not SGI Visual Workstation 320/540"); */
399 }
400
401 li_pcia_write16(LI_PCI_INTEN, ALLDEVS);
402 li_pcib_write16(LI_PCI_INTEN, ALLDEVS);
403}
404
405static __init void cobalt_init(void)
406{
407 /*
408 * On normal SMP PC this is used only with SMP, but we have to
409 * use it and set it up here to start the Cobalt clock
410 */
411 set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
412 setup_local_APIC();
413 printk(KERN_INFO "Local APIC Version %#x, ID %#x\n",
414 (unsigned int)apic_read(APIC_LVR),
415 (unsigned int)apic_read(APIC_ID));
416
417 set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
418 set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
419 printk(KERN_INFO "Cobalt Revision %#lx, APIC ID %#lx\n",
420 co_cpu_read(CO_CPU_REV), co_apic_read(CO_APIC_ID));
421
422 /* Enable Cobalt APIC being careful to NOT change the ID! */
423 co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID) | CO_APIC_ENABLE);
424
425 printk(KERN_INFO "Cobalt APIC enabled: ID reg %#lx\n",
426 co_apic_read(CO_APIC_ID));
427}
428
429int __init visws_trap_init_quirk(void)
430{
431 lithium_init();
432 cobalt_init();
433
434 return 1;
435}
436
437/*
438 * IRQ controller / APIC support:
439 */
440
441static DEFINE_SPINLOCK(cobalt_lock);
442
443/*
444 * Set the given Cobalt APIC Redirection Table entry to point
445 * to the given IDT vector/index.
446 */
447static inline void co_apic_set(int entry, int irq)
448{
449 co_apic_write(CO_APIC_LO(entry), CO_APIC_LEVEL | (irq + FIRST_EXTERNAL_VECTOR));
450 co_apic_write(CO_APIC_HI(entry), 0);
451}
452
453/*
454 * Cobalt (IO)-APIC functions to handle PCI devices.
455 */
456static inline int co_apic_ide0_hack(void)
457{
458 extern char visws_board_type;
459 extern char visws_board_rev;
460
461 if (visws_board_type == VISWS_320 && visws_board_rev == 5)
462 return 5;
463 return CO_APIC_IDE0;
464}
465
466static int is_co_apic(unsigned int irq)
467{
468 if (IS_CO_APIC(irq))
469 return CO_APIC(irq);
470
471 switch (irq) {
472 case 0: return CO_APIC_CPU;
473 case CO_IRQ_IDE0: return co_apic_ide0_hack();
474 case CO_IRQ_IDE1: return CO_APIC_IDE1;
475 default: return -1;
476 }
477}
478
479
480/*
481 * This is the SGI Cobalt (IO-)APIC:
482 */
483
484static void enable_cobalt_irq(unsigned int irq)
485{
486 co_apic_set(is_co_apic(irq), irq);
487}
488
489static void disable_cobalt_irq(unsigned int irq)
490{
491 int entry = is_co_apic(irq);
492
493 co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK);
494 co_apic_read(CO_APIC_LO(entry));
495}
496
497/*
498 * "irq" really just serves to identify the device. Here is where we
499 * map this to the Cobalt APIC entry where it's physically wired.
500 * This is called via request_irq -> setup_irq -> irq_desc->startup()
501 */
502static unsigned int startup_cobalt_irq(unsigned int irq)
503{
504 unsigned long flags;
505
506 spin_lock_irqsave(&cobalt_lock, flags);
507 if ((irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
508 irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
509 enable_cobalt_irq(irq);
510 spin_unlock_irqrestore(&cobalt_lock, flags);
511 return 0;
512}
513
514static void ack_cobalt_irq(unsigned int irq)
515{
516 unsigned long flags;
517
518 spin_lock_irqsave(&cobalt_lock, flags);
519 disable_cobalt_irq(irq);
520 apic_write(APIC_EOI, APIC_EIO_ACK);
521 spin_unlock_irqrestore(&cobalt_lock, flags);
522}
523
524static void end_cobalt_irq(unsigned int irq)
525{
526 unsigned long flags;
527
528 spin_lock_irqsave(&cobalt_lock, flags);
529 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
530 enable_cobalt_irq(irq);
531 spin_unlock_irqrestore(&cobalt_lock, flags);
532}
533
534static struct irq_chip cobalt_irq_type = {
535 .typename = "Cobalt-APIC",
536 .startup = startup_cobalt_irq,
537 .shutdown = disable_cobalt_irq,
538 .enable = enable_cobalt_irq,
539 .disable = disable_cobalt_irq,
540 .ack = ack_cobalt_irq,
541 .end = end_cobalt_irq,
542};
543
544
545/*
546 * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt
547 * -- not the manner expected by the code in i8259.c.
548 *
549 * there is a 'master' physical interrupt source that gets sent to
550 * the CPU. But in the chipset there are various 'virtual' interrupts
551 * waiting to be handled. We represent this to Linux through a 'master'
552 * interrupt controller type, and through a special virtual interrupt-
553 * controller. Device drivers only see the virtual interrupt sources.
554 */
555static unsigned int startup_piix4_master_irq(unsigned int irq)
556{
557 init_8259A(0);
558
559 return startup_cobalt_irq(irq);
560}
561
562static void end_piix4_master_irq(unsigned int irq)
563{
564 unsigned long flags;
565
566 spin_lock_irqsave(&cobalt_lock, flags);
567 enable_cobalt_irq(irq);
568 spin_unlock_irqrestore(&cobalt_lock, flags);
569}
570
571static struct irq_chip piix4_master_irq_type = {
572 .typename = "PIIX4-master",
573 .startup = startup_piix4_master_irq,
574 .ack = ack_cobalt_irq,
575 .end = end_piix4_master_irq,
576};
577
578
579static struct irq_chip piix4_virtual_irq_type = {
580 .typename = "PIIX4-virtual",
581 .shutdown = disable_8259A_irq,
582 .enable = enable_8259A_irq,
583 .disable = disable_8259A_irq,
584};
585
586
587/*
588 * PIIX4-8259 master/virtual functions to handle interrupt requests
589 * from legacy devices: floppy, parallel, serial, rtc.
590 *
591 * None of these get Cobalt APIC entries, neither do they have IDT
592 * entries. These interrupts are purely virtual and distributed from
593 * the 'master' interrupt source: CO_IRQ_8259.
594 *
595 * When the 8259 interrupts its handler figures out which of these
596 * devices is interrupting and dispatches to its handler.
597 *
598 * CAREFUL: devices see the 'virtual' interrupt only. Thus disable/
599 * enable_irq gets the right irq. This 'master' irq is never directly
600 * manipulated by any driver.
601 */
602static irqreturn_t piix4_master_intr(int irq, void *dev_id)
603{
604 int realirq;
605 irq_desc_t *desc;
606 unsigned long flags;
607
608 spin_lock_irqsave(&i8259A_lock, flags);
609
610 /* Find out what's interrupting in the PIIX4 master 8259 */
611 outb(0x0c, 0x20); /* OCW3 Poll command */
612 realirq = inb(0x20);
613
614 /*
615 * Bit 7 == 0 means invalid/spurious
616 */
617 if (unlikely(!(realirq & 0x80)))
618 goto out_unlock;
619
620 realirq &= 7;
621
622 if (unlikely(realirq == 2)) {
623 outb(0x0c, 0xa0);
624 realirq = inb(0xa0);
625
626 if (unlikely(!(realirq & 0x80)))
627 goto out_unlock;
628
629 realirq = (realirq & 7) + 8;
630 }
631
632 /* mask and ack interrupt */
633 cached_irq_mask |= 1 << realirq;
634 if (unlikely(realirq > 7)) {
635 inb(0xa1);
636 outb(cached_slave_mask, 0xa1);
637 outb(0x60 + (realirq & 7), 0xa0);
638 outb(0x60 + 2, 0x20);
639 } else {
640 inb(0x21);
641 outb(cached_master_mask, 0x21);
642 outb(0x60 + realirq, 0x20);
643 }
644
645 spin_unlock_irqrestore(&i8259A_lock, flags);
646
647 desc = irq_desc + realirq;
648
649 /*
650 * handle this 'virtual interrupt' as a Cobalt one now.
651 */
652 kstat_cpu(smp_processor_id()).irqs[realirq]++;
653
654 if (likely(desc->action != NULL))
655 handle_IRQ_event(realirq, desc->action);
656
657 if (!(desc->status & IRQ_DISABLED))
658 enable_8259A_irq(realirq);
659
660 return IRQ_HANDLED;
661
662out_unlock:
663 spin_unlock_irqrestore(&i8259A_lock, flags);
664 return IRQ_NONE;
665}
666
667static struct irqaction master_action = {
668 .handler = piix4_master_intr,
669 .name = "PIIX4-8259",
670};
671
672static struct irqaction cascade_action = {
673 .handler = no_action,
674 .name = "cascade",
675};
676
677
678void init_VISWS_APIC_irqs(void)
679{
680 int i;
681
682 for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
683 irq_desc[i].status = IRQ_DISABLED;
684 irq_desc[i].action = 0;
685 irq_desc[i].depth = 1;
686
687 if (i == 0) {
688 irq_desc[i].chip = &cobalt_irq_type;
689 }
690 else if (i == CO_IRQ_IDE0) {
691 irq_desc[i].chip = &cobalt_irq_type;
692 }
693 else if (i == CO_IRQ_IDE1) {
694 irq_desc[i].chip = &cobalt_irq_type;
695 }
696 else if (i == CO_IRQ_8259) {
697 irq_desc[i].chip = &piix4_master_irq_type;
698 }
699 else if (i < CO_IRQ_APIC0) {
700 irq_desc[i].chip = &piix4_virtual_irq_type;
701 }
702 else if (IS_CO_APIC(i)) {
703 irq_desc[i].chip = &cobalt_irq_type;
704 }
705 }
706
707 setup_irq(CO_IRQ_8259, &master_action);
708 setup_irq(2, &cascade_action);
709}
diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig
index 964dfa36d367..c70e12b1a637 100644
--- a/arch/x86/lguest/Kconfig
+++ b/arch/x86/lguest/Kconfig
@@ -3,7 +3,7 @@ config LGUEST_GUEST
3 select PARAVIRT 3 select PARAVIRT
4 depends on X86_32 4 depends on X86_32
5 depends on !X86_PAE 5 depends on !X86_PAE
6 depends on !(X86_VISWS || X86_VOYAGER) 6 depends on !X86_VOYAGER
7 select VIRTIO 7 select VIRTIO
8 select VIRTIO_RING 8 select VIRTIO_RING
9 select VIRTIO_CONSOLE 9 select VIRTIO_CONSOLE
diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c
index 2f5e277686b8..48278fa7d3de 100644
--- a/arch/x86/mach-default/setup.c
+++ b/arch/x86/mach-default/setup.c
@@ -10,6 +10,14 @@
10#include <asm/e820.h> 10#include <asm/e820.h>
11#include <asm/setup.h> 11#include <asm/setup.h>
12 12
13/*
14 * Any quirks to be performed to initialize timers/irqs/etc?
15 */
16int (*arch_time_init_quirk)(void);
17int (*arch_pre_intr_init_quirk)(void);
18int (*arch_intr_init_quirk)(void);
19int (*arch_trap_init_quirk)(void);
20
13#ifdef CONFIG_HOTPLUG_CPU 21#ifdef CONFIG_HOTPLUG_CPU
14#define DEFAULT_SEND_IPI (1) 22#define DEFAULT_SEND_IPI (1)
15#else 23#else
@@ -29,6 +37,10 @@ int no_broadcast=DEFAULT_SEND_IPI;
29 **/ 37 **/
30void __init pre_intr_init_hook(void) 38void __init pre_intr_init_hook(void)
31{ 39{
40 if (arch_pre_intr_init_quirk) {
41 if (arch_pre_intr_init_quirk())
42 return;
43 }
32 init_ISA_irqs(); 44 init_ISA_irqs();
33} 45}
34 46
@@ -52,6 +64,10 @@ static struct irqaction irq2 = {
52 **/ 64 **/
53void __init intr_init_hook(void) 65void __init intr_init_hook(void)
54{ 66{
67 if (arch_intr_init_quirk) {
68 if (arch_intr_init_quirk())
69 return;
70 }
55#ifdef CONFIG_X86_LOCAL_APIC 71#ifdef CONFIG_X86_LOCAL_APIC
56 apic_intr_init(); 72 apic_intr_init();
57#endif 73#endif
@@ -65,7 +81,7 @@ void __init intr_init_hook(void)
65 * 81 *
66 * Description: 82 * Description:
67 * generally used to activate any machine specific identification 83 * generally used to activate any machine specific identification
68 * routines that may be needed before setup_arch() runs. On VISWS 84 * routines that may be needed before setup_arch() runs. On Voyager
69 * this is used to get the board revision and type. 85 * this is used to get the board revision and type.
70 **/ 86 **/
71void __init pre_setup_arch_hook(void) 87void __init pre_setup_arch_hook(void)
@@ -81,6 +97,10 @@ void __init pre_setup_arch_hook(void)
81 **/ 97 **/
82void __init trap_init_hook(void) 98void __init trap_init_hook(void)
83{ 99{
100 if (arch_trap_init_quirk) {
101 if (arch_trap_init_quirk())
102 return;
103 }
84} 104}
85 105
86static struct irqaction irq0 = { 106static struct irqaction irq0 = {
@@ -99,6 +119,16 @@ static struct irqaction irq0 = {
99 **/ 119 **/
100void __init time_init_hook(void) 120void __init time_init_hook(void)
101{ 121{
122 if (arch_time_init_quirk) {
123 /*
124 * A nonzero return code does not mean failure, it means
125 * that the architecture quirk does not want any
126 * generic (timer) setup to be performed after this:
127 */
128 if (arch_time_init_quirk())
129 return;
130 }
131
102 irq0.mask = cpumask_of_cpu(0); 132 irq0.mask = cpumask_of_cpu(0);
103 setup_irq(0, &irq0); 133 setup_irq(0, &irq0);
104} 134}
diff --git a/arch/x86/mach-visws/Makefile b/arch/x86/mach-visws/Makefile
deleted file mode 100644
index 835fd96ad768..000000000000
--- a/arch/x86/mach-visws/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
1#
2# Makefile for the linux kernel.
3#
4
5obj-y := setup.o traps.o reboot.o
6
7obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
8obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o
diff --git a/arch/x86/mach-visws/mpparse.c b/arch/x86/mach-visws/mpparse.c
deleted file mode 100644
index a2fb78c0d154..000000000000
--- a/arch/x86/mach-visws/mpparse.c
+++ /dev/null
@@ -1,85 +0,0 @@
1
2#include <linux/init.h>
3#include <linux/smp.h>
4
5#include <asm/smp.h>
6#include <asm/io.h>
7
8#include "cobalt.h"
9#include "mach_apic.h"
10
11extern unsigned int __cpuinitdata maxcpus;
12
13/*
14 * The Visual Workstation is Intel MP compliant in the hardware
15 * sense, but it doesn't have a BIOS(-configuration table).
16 * No problem for Linux.
17 */
18
19static void __init MP_processor_info (struct mpc_config_processor *m)
20{
21 int ver, logical_apicid;
22 physid_mask_t apic_cpus;
23
24 if (!(m->mpc_cpuflag & CPU_ENABLED))
25 return;
26
27 logical_apicid = m->mpc_apicid;
28 printk(KERN_INFO "%sCPU #%d %u:%u APIC version %d\n",
29 m->mpc_cpuflag & CPU_BOOTPROCESSOR ? "Bootup " : "",
30 m->mpc_apicid,
31 (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
32 (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
33 m->mpc_apicver);
34
35 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR)
36 boot_cpu_physical_apicid = m->mpc_apicid;
37
38 ver = m->mpc_apicver;
39 if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) {
40 printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
41 m->mpc_apicid, MAX_APICS);
42 return;
43 }
44
45 apic_cpus = apicid_to_cpu_present(m->mpc_apicid);
46 physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus);
47 /*
48 * Validate version
49 */
50 if (ver == 0x0) {
51 printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! "
52 "fixing up to 0x10. (tell your hw vendor)\n",
53 m->mpc_apicid);
54 ver = 0x10;
55 }
56 apic_version[m->mpc_apicid] = ver;
57}
58
59void __init find_smp_config(void)
60{
61 struct mpc_config_processor *mp = phys_to_virt(CO_CPU_TAB_PHYS);
62 unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS));
63
64 if (ncpus > CO_CPU_MAX) {
65 printk(KERN_WARNING "find_visws_smp: got cpu count of %d at %p\n",
66 ncpus, mp);
67
68 ncpus = CO_CPU_MAX;
69 }
70
71 if (ncpus > maxcpus)
72 ncpus = maxcpus;
73
74#ifdef CONFIG_X86_LOCAL_APIC
75 smp_found_config = 1;
76#endif
77 while (ncpus--)
78 MP_processor_info(mp++);
79
80 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
81}
82
83void __init get_smp_config (void)
84{
85}
diff --git a/arch/x86/mach-visws/reboot.c b/arch/x86/mach-visws/reboot.c
deleted file mode 100644
index 99332abfad42..000000000000
--- a/arch/x86/mach-visws/reboot.c
+++ /dev/null
@@ -1,55 +0,0 @@
1#include <linux/module.h>
2#include <linux/smp.h>
3#include <linux/delay.h>
4
5#include <asm/io.h>
6#include "piix4.h"
7
8void (*pm_power_off)(void);
9EXPORT_SYMBOL(pm_power_off);
10
11void machine_shutdown(void)
12{
13#ifdef CONFIG_SMP
14 smp_send_stop();
15#endif
16}
17
18void machine_emergency_restart(void)
19{
20 /*
21 * Visual Workstations restart after this
22 * register is poked on the PIIX4
23 */
24 outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT);
25}
26
27void machine_restart(char * __unused)
28{
29 machine_shutdown();
30 machine_emergency_restart();
31}
32
33void machine_power_off(void)
34{
35 unsigned short pm_status;
36 extern unsigned int pci_bus0;
37
38 while ((pm_status = inw(PMSTS_PORT)) & 0x100)
39 outw(pm_status, PMSTS_PORT);
40
41 outw(PM_SUSPEND_ENABLE, PMCNTRL_PORT);
42
43 mdelay(10);
44
45#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
46 (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
47
48 outl(PCI_CONF1_ADDRESS(pci_bus0, SPECIAL_DEV, SPECIAL_REG), 0xCF8);
49 outl(PIIX_SPECIAL_STOP, 0xCFC);
50}
51
52void machine_halt(void)
53{
54}
55
diff --git a/arch/x86/mach-visws/setup.c b/arch/x86/mach-visws/setup.c
deleted file mode 100644
index d67868ec9b7f..000000000000
--- a/arch/x86/mach-visws/setup.c
+++ /dev/null
@@ -1,183 +0,0 @@
1/*
2 * Unmaintained SGI Visual Workstation support.
3 * Split out from setup.c by davej@suse.de
4 */
5
6#include <linux/smp.h>
7#include <linux/init.h>
8#include <linux/interrupt.h>
9#include <linux/module.h>
10
11#include <asm/fixmap.h>
12#include <asm/arch_hooks.h>
13#include <asm/io.h>
14#include <asm/e820.h>
15#include <asm/setup.h>
16#include "cobalt.h"
17#include "piix4.h"
18
19int no_broadcast;
20
21char visws_board_type = -1;
22char visws_board_rev = -1;
23
24void __init visws_get_board_type_and_rev(void)
25{
26 int raw;
27
28 visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
29 >> PIIX_GPI_BD_SHIFT;
30 /*
31 * Get Board rev.
32 * First, we have to initialize the 307 part to allow us access
33 * to the GPIO registers. Let's map them at 0x0fc0 which is right
34 * after the PIIX4 PM section.
35 */
36 outb_p(SIO_DEV_SEL, SIO_INDEX);
37 outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
38
39 outb_p(SIO_DEV_MSB, SIO_INDEX);
40 outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
41
42 outb_p(SIO_DEV_LSB, SIO_INDEX);
43 outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
44
45 outb_p(SIO_DEV_ENB, SIO_INDEX);
46 outb_p(1, SIO_DATA); /* Enable GPIO registers. */
47
48 /*
49 * Now, we have to map the power management section to write
50 * a bit which enables access to the GPIO registers.
51 * What lunatic came up with this shit?
52 */
53 outb_p(SIO_DEV_SEL, SIO_INDEX);
54 outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
55
56 outb_p(SIO_DEV_MSB, SIO_INDEX);
57 outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */
58
59 outb_p(SIO_DEV_LSB, SIO_INDEX);
60 outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */
61
62 outb_p(SIO_DEV_ENB, SIO_INDEX);
63 outb_p(1, SIO_DATA); /* Enable PM registers. */
64
65 /*
66 * Now, write the PM register which enables the GPIO registers.
67 */
68 outb_p(SIO_PM_FER2, SIO_PM_INDEX);
69 outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
70
71 /*
72 * Now, initialize the GPIO registers.
73 * We want them all to be inputs which is the
74 * power on default, so let's leave them alone.
75 * So, let's just read the board rev!
76 */
77 raw = inb_p(SIO_GP_DATA1);
78 raw &= 0x7f; /* 7 bits of valid board revision ID. */
79
80 if (visws_board_type == VISWS_320) {
81 if (raw < 0x6) {
82 visws_board_rev = 4;
83 } else if (raw < 0xc) {
84 visws_board_rev = 5;
85 } else {
86 visws_board_rev = 6;
87 }
88 } else if (visws_board_type == VISWS_540) {
89 visws_board_rev = 2;
90 } else {
91 visws_board_rev = raw;
92 }
93
94 printk(KERN_INFO "Silicon Graphics Visual Workstation %s (rev %d) detected\n",
95 (visws_board_type == VISWS_320 ? "320" :
96 (visws_board_type == VISWS_540 ? "540" :
97 "unknown")), visws_board_rev);
98}
99
100void __init pre_intr_init_hook(void)
101{
102 init_VISWS_APIC_irqs();
103}
104
105void __init intr_init_hook(void)
106{
107#ifdef CONFIG_X86_LOCAL_APIC
108 apic_intr_init();
109#endif
110}
111
112void __init pre_setup_arch_hook()
113{
114 visws_get_board_type_and_rev();
115}
116
117static struct irqaction irq0 = {
118 .handler = timer_interrupt,
119 .flags = IRQF_DISABLED | IRQF_IRQPOLL,
120 .name = "timer",
121};
122
123void __init time_init_hook(void)
124{
125 printk(KERN_INFO "Starting Cobalt Timer system clock\n");
126
127 /* Set the countdown value */
128 co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
129
130 /* Start the timer */
131 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
132
133 /* Enable (unmask) the timer interrupt */
134 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
135
136 /* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
137 setup_irq(0, &irq0);
138}
139
140/* Hook for machine specific memory setup. */
141
142#define MB (1024 * 1024)
143
144unsigned long sgivwfb_mem_phys;
145unsigned long sgivwfb_mem_size;
146EXPORT_SYMBOL(sgivwfb_mem_phys);
147EXPORT_SYMBOL(sgivwfb_mem_size);
148
149long long mem_size __initdata = 0;
150
151char * __init machine_specific_memory_setup(void)
152{
153 long long gfx_mem_size = 8 * MB;
154
155 mem_size = boot_params.alt_mem_k;
156
157 if (!mem_size) {
158 printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
159 mem_size = 128 * MB;
160 }
161
162 /*
163 * this hardcodes the graphics memory to 8 MB
164 * it really should be sized dynamically (or at least
165 * set as a boot param)
166 */
167 if (!sgivwfb_mem_size) {
168 printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
169 sgivwfb_mem_size = 8 * MB;
170 }
171
172 /*
173 * Trim to nearest MB
174 */
175 sgivwfb_mem_size &= ~((1 << 20) - 1);
176 sgivwfb_mem_phys = mem_size - gfx_mem_size;
177
178 e820_add_region(0, LOWMEMSIZE(), E820_RAM);
179 e820_add_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
180 e820_add_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);
181
182 return "PROM";
183}
diff --git a/arch/x86/mach-visws/traps.c b/arch/x86/mach-visws/traps.c
deleted file mode 100644
index bfac6ba10f8a..000000000000
--- a/arch/x86/mach-visws/traps.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/* VISWS traps */
2
3#include <linux/sched.h>
4#include <linux/kernel.h>
5#include <linux/init.h>
6#include <linux/pci.h>
7#include <linux/pci_ids.h>
8
9#include <asm/io.h>
10#include <asm/arch_hooks.h>
11#include <asm/apic.h>
12#include "cobalt.h"
13#include "lithium.h"
14
15
16#define A01234 (LI_INTA_0 | LI_INTA_1 | LI_INTA_2 | LI_INTA_3 | LI_INTA_4)
17#define BCD (LI_INTB | LI_INTC | LI_INTD)
18#define ALLDEVS (A01234 | BCD)
19
20static __init void lithium_init(void)
21{
22 set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
23 set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
24
25 if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
26 (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
27 printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A');
28 panic("This machine is not SGI Visual Workstation 320/540");
29 }
30
31 if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
32 (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
33 printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B');
34 panic("This machine is not SGI Visual Workstation 320/540");
35 }
36
37 li_pcia_write16(LI_PCI_INTEN, ALLDEVS);
38 li_pcib_write16(LI_PCI_INTEN, ALLDEVS);
39}
40
41static __init void cobalt_init(void)
42{
43 /*
44 * On normal SMP PC this is used only with SMP, but we have to
45 * use it and set it up here to start the Cobalt clock
46 */
47 set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
48 setup_local_APIC();
49 printk(KERN_INFO "Local APIC Version %#x, ID %#x\n",
50 (unsigned int)apic_read(APIC_LVR),
51 (unsigned int)apic_read(APIC_ID));
52
53 set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
54 set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
55 printk(KERN_INFO "Cobalt Revision %#lx, APIC ID %#lx\n",
56 co_cpu_read(CO_CPU_REV), co_apic_read(CO_APIC_ID));
57
58 /* Enable Cobalt APIC being careful to NOT change the ID! */
59 co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID) | CO_APIC_ENABLE);
60
61 printk(KERN_INFO "Cobalt APIC enabled: ID reg %#lx\n",
62 co_apic_read(CO_APIC_ID));
63}
64
65void __init trap_init_hook(void)
66{
67 lithium_init();
68 cobalt_init();
69}
diff --git a/arch/x86/mach-visws/visws_apic.c b/arch/x86/mach-visws/visws_apic.c
deleted file mode 100644
index d8b2cfd85d92..000000000000
--- a/arch/x86/mach-visws/visws_apic.c
+++ /dev/null
@@ -1,296 +0,0 @@
1/*
2 * Copyright (C) 1999 Bent Hagemark, Ingo Molnar
3 *
4 * SGI Visual Workstation interrupt controller
5 *
6 * The Cobalt system ASIC in the Visual Workstation contains a "Cobalt" APIC
7 * which serves as the main interrupt controller in the system. Non-legacy
8 * hardware in the system uses this controller directly. Legacy devices
9 * are connected to the PIIX4 which in turn has its 8259(s) connected to
10 * a of the Cobalt APIC entry.
11 *
12 * 09/02/2000 - Updated for 2.4 by jbarnes@sgi.com
13 *
14 * 25/11/2002 - Updated for 2.5 by Andrey Panin <pazke@orbita1.ru>
15 */
16
17#include <linux/kernel_stat.h>
18#include <linux/interrupt.h>
19#include <linux/init.h>
20
21#include <asm/io.h>
22#include <asm/apic.h>
23#include <asm/i8259.h>
24#include <asm/irq_vectors.h>
25
26#include "cobalt.h"
27
28static DEFINE_SPINLOCK(cobalt_lock);
29
30/*
31 * Set the given Cobalt APIC Redirection Table entry to point
32 * to the given IDT vector/index.
33 */
34static inline void co_apic_set(int entry, int irq)
35{
36 co_apic_write(CO_APIC_LO(entry), CO_APIC_LEVEL | (irq + FIRST_EXTERNAL_VECTOR));
37 co_apic_write(CO_APIC_HI(entry), 0);
38}
39
40/*
41 * Cobalt (IO)-APIC functions to handle PCI devices.
42 */
43static inline int co_apic_ide0_hack(void)
44{
45 extern char visws_board_type;
46 extern char visws_board_rev;
47
48 if (visws_board_type == VISWS_320 && visws_board_rev == 5)
49 return 5;
50 return CO_APIC_IDE0;
51}
52
53static int is_co_apic(unsigned int irq)
54{
55 if (IS_CO_APIC(irq))
56 return CO_APIC(irq);
57
58 switch (irq) {
59 case 0: return CO_APIC_CPU;
60 case CO_IRQ_IDE0: return co_apic_ide0_hack();
61 case CO_IRQ_IDE1: return CO_APIC_IDE1;
62 default: return -1;
63 }
64}
65
66
67/*
68 * This is the SGI Cobalt (IO-)APIC:
69 */
70
71static void enable_cobalt_irq(unsigned int irq)
72{
73 co_apic_set(is_co_apic(irq), irq);
74}
75
76static void disable_cobalt_irq(unsigned int irq)
77{
78 int entry = is_co_apic(irq);
79
80 co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK);
81 co_apic_read(CO_APIC_LO(entry));
82}
83
84/*
85 * "irq" really just serves to identify the device. Here is where we
86 * map this to the Cobalt APIC entry where it's physically wired.
87 * This is called via request_irq -> setup_irq -> irq_desc->startup()
88 */
89static unsigned int startup_cobalt_irq(unsigned int irq)
90{
91 unsigned long flags;
92
93 spin_lock_irqsave(&cobalt_lock, flags);
94 if ((irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
95 irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
96 enable_cobalt_irq(irq);
97 spin_unlock_irqrestore(&cobalt_lock, flags);
98 return 0;
99}
100
101static void ack_cobalt_irq(unsigned int irq)
102{
103 unsigned long flags;
104
105 spin_lock_irqsave(&cobalt_lock, flags);
106 disable_cobalt_irq(irq);
107 apic_write(APIC_EOI, APIC_EIO_ACK);
108 spin_unlock_irqrestore(&cobalt_lock, flags);
109}
110
111static void end_cobalt_irq(unsigned int irq)
112{
113 unsigned long flags;
114
115 spin_lock_irqsave(&cobalt_lock, flags);
116 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
117 enable_cobalt_irq(irq);
118 spin_unlock_irqrestore(&cobalt_lock, flags);
119}
120
121static struct irq_chip cobalt_irq_type = {
122 .typename = "Cobalt-APIC",
123 .startup = startup_cobalt_irq,
124 .shutdown = disable_cobalt_irq,
125 .enable = enable_cobalt_irq,
126 .disable = disable_cobalt_irq,
127 .ack = ack_cobalt_irq,
128 .end = end_cobalt_irq,
129};
130
131
132/*
133 * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt
134 * -- not the manner expected by the code in i8259.c.
135 *
136 * there is a 'master' physical interrupt source that gets sent to
137 * the CPU. But in the chipset there are various 'virtual' interrupts
138 * waiting to be handled. We represent this to Linux through a 'master'
139 * interrupt controller type, and through a special virtual interrupt-
140 * controller. Device drivers only see the virtual interrupt sources.
141 */
142static unsigned int startup_piix4_master_irq(unsigned int irq)
143{
144 init_8259A(0);
145
146 return startup_cobalt_irq(irq);
147}
148
149static void end_piix4_master_irq(unsigned int irq)
150{
151 unsigned long flags;
152
153 spin_lock_irqsave(&cobalt_lock, flags);
154 enable_cobalt_irq(irq);
155 spin_unlock_irqrestore(&cobalt_lock, flags);
156}
157
158static struct irq_chip piix4_master_irq_type = {
159 .typename = "PIIX4-master",
160 .startup = startup_piix4_master_irq,
161 .ack = ack_cobalt_irq,
162 .end = end_piix4_master_irq,
163};
164
165
166static struct irq_chip piix4_virtual_irq_type = {
167 .typename = "PIIX4-virtual",
168 .shutdown = disable_8259A_irq,
169 .enable = enable_8259A_irq,
170 .disable = disable_8259A_irq,
171};
172
173
174/*
175 * PIIX4-8259 master/virtual functions to handle interrupt requests
176 * from legacy devices: floppy, parallel, serial, rtc.
177 *
178 * None of these get Cobalt APIC entries, neither do they have IDT
179 * entries. These interrupts are purely virtual and distributed from
180 * the 'master' interrupt source: CO_IRQ_8259.
181 *
182 * When the 8259 interrupts its handler figures out which of these
183 * devices is interrupting and dispatches to its handler.
184 *
185 * CAREFUL: devices see the 'virtual' interrupt only. Thus disable/
186 * enable_irq gets the right irq. This 'master' irq is never directly
187 * manipulated by any driver.
188 */
189static irqreturn_t piix4_master_intr(int irq, void *dev_id)
190{
191 int realirq;
192 irq_desc_t *desc;
193 unsigned long flags;
194
195 spin_lock_irqsave(&i8259A_lock, flags);
196
197 /* Find out what's interrupting in the PIIX4 master 8259 */
198 outb(0x0c, 0x20); /* OCW3 Poll command */
199 realirq = inb(0x20);
200
201 /*
202 * Bit 7 == 0 means invalid/spurious
203 */
204 if (unlikely(!(realirq & 0x80)))
205 goto out_unlock;
206
207 realirq &= 7;
208
209 if (unlikely(realirq == 2)) {
210 outb(0x0c, 0xa0);
211 realirq = inb(0xa0);
212
213 if (unlikely(!(realirq & 0x80)))
214 goto out_unlock;
215
216 realirq = (realirq & 7) + 8;
217 }
218
219 /* mask and ack interrupt */
220 cached_irq_mask |= 1 << realirq;
221 if (unlikely(realirq > 7)) {
222 inb(0xa1);
223 outb(cached_slave_mask, 0xa1);
224 outb(0x60 + (realirq & 7), 0xa0);
225 outb(0x60 + 2, 0x20);
226 } else {
227 inb(0x21);
228 outb(cached_master_mask, 0x21);
229 outb(0x60 + realirq, 0x20);
230 }
231
232 spin_unlock_irqrestore(&i8259A_lock, flags);
233
234 desc = irq_desc + realirq;
235
236 /*
237 * handle this 'virtual interrupt' as a Cobalt one now.
238 */
239 kstat_cpu(smp_processor_id()).irqs[realirq]++;
240
241 if (likely(desc->action != NULL))
242 handle_IRQ_event(realirq, desc->action);
243
244 if (!(desc->status & IRQ_DISABLED))
245 enable_8259A_irq(realirq);
246
247 return IRQ_HANDLED;
248
249out_unlock:
250 spin_unlock_irqrestore(&i8259A_lock, flags);
251 return IRQ_NONE;
252}
253
254static struct irqaction master_action = {
255 .handler = piix4_master_intr,
256 .name = "PIIX4-8259",
257};
258
259static struct irqaction cascade_action = {
260 .handler = no_action,
261 .name = "cascade",
262};
263
264
265void init_VISWS_APIC_irqs(void)
266{
267 int i;
268
269 for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
270 irq_desc[i].status = IRQ_DISABLED;
271 irq_desc[i].action = 0;
272 irq_desc[i].depth = 1;
273
274 if (i == 0) {
275 irq_desc[i].chip = &cobalt_irq_type;
276 }
277 else if (i == CO_IRQ_IDE0) {
278 irq_desc[i].chip = &cobalt_irq_type;
279 }
280 else if (i == CO_IRQ_IDE1) {
281 irq_desc[i].chip = &cobalt_irq_type;
282 }
283 else if (i == CO_IRQ_8259) {
284 irq_desc[i].chip = &piix4_master_irq_type;
285 }
286 else if (i < CO_IRQ_APIC0) {
287 irq_desc[i].chip = &piix4_virtual_irq_type;
288 }
289 else if (IS_CO_APIC(i)) {
290 irq_desc[i].chip = &cobalt_irq_type;
291 }
292 }
293
294 setup_irq(CO_IRQ_8259, &master_action);
295 setup_irq(2, &cascade_action);
296}
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index 99d9f095e4d4..e515e8db842a 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -9,9 +9,7 @@ pci-y := fixup.o
9pci-$(CONFIG_ACPI) += acpi.o 9pci-$(CONFIG_ACPI) += acpi.o
10pci-y += legacy.o irq.o 10pci-y += legacy.o irq.o
11 11
12# Careful: VISWS overrule the pci-y above. The colons are 12pci-$(CONFIG_X86_VISWS) += visws.o
13# therefor correct. This needs a proper fix by distangling the code.
14pci-$(CONFIG_X86_VISWS) := visws.o fixup.o
15 13
16pci-$(CONFIG_X86_NUMAQ) += numa.o 14pci-$(CONFIG_X86_NUMAQ) += numa.o
17 15
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 3c1d795cbbe9..132876cc6fca 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -62,6 +62,11 @@ int __init pci_subsys_init(void)
62#endif 62#endif
63 pci_legacy_init(); 63 pci_legacy_init();
64 pcibios_irq_init(); 64 pcibios_irq_init();
65#ifdef CONFIG_X86_NUMAQ
66 pci_numa_init();
67#endif
65 pcibios_init(); 68 pcibios_init();
69
70 return 0;
66} 71}
67subsys_initcall(pci_subsys_init); 72subsys_initcall(pci_subsys_init);
diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c
index e1620dc8649a..8b5ca1966731 100644
--- a/arch/x86/pci/numa.c
+++ b/arch/x86/pci/numa.c
@@ -151,7 +151,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
151} 151}
152DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); 152DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
153 153
154static int __init pci_numa_init(void) 154int __init pci_numa_init(void)
155{ 155{
156 int quad; 156 int quad;
157 157
@@ -176,11 +176,3 @@ static int __init pci_numa_init(void)
176 } 176 }
177 return 0; 177 return 0;
178} 178}
179
180static __init int pci_subsys_init(void)
181{
182 pci_numa_init();
183 pcibios_irq_init();
184 pcibios_init();
185}
186subsys_initcall(pci_subsys_init);
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 58241748470f..b2270a55b0cf 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -107,6 +107,7 @@ extern void __init dmi_check_skip_isa_align(void);
107/* some common used subsys_initcalls */ 107/* some common used subsys_initcalls */
108extern int __init pci_acpi_init(void); 108extern int __init pci_acpi_init(void);
109extern int __init pcibios_irq_init(void); 109extern int __init pcibios_irq_init(void);
110extern int __init pci_numa_init(void);
110extern int __init pcibios_init(void); 111extern int __init pcibios_init(void);
111 112
112/* pci-mmconfig.c */ 113/* pci-mmconfig.c */
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index 16e52063ecb3..1a7bed492bb1 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -8,18 +8,19 @@
8#include <linux/pci.h> 8#include <linux/pci.h>
9#include <linux/init.h> 9#include <linux/init.h>
10 10
11#include "cobalt.h" 11#include <asm/setup.h>
12#include "lithium.h" 12#include <asm/visws/cobalt.h>
13#include <asm/visws/lithium.h>
13 14
14#include "pci.h" 15#include "pci.h"
15 16
16static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } 17static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
17static void pci_visws_disable_irq(struct pci_dev *dev) { } 18static void pci_visws_disable_irq(struct pci_dev *dev) { }
18 19
19int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; 20/* int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; */
20void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq; 21/* void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq; */
21 22
22void __init pcibios_penalize_isa_irq(int irq, int active) {} 23/* void __init pcibios_penalize_isa_irq(int irq, int active) {} */
23 24
24 25
25unsigned int pci_bus0, pci_bus1; 26unsigned int pci_bus0, pci_bus1;
@@ -107,7 +108,15 @@ static int __init pci_visws_init(void)
107 108
108static __init int pci_subsys_init(void) 109static __init int pci_subsys_init(void)
109{ 110{
111 if (!is_visws_box())
112 return -1;
113
114 pcibios_enable_irq = &pci_visws_enable_irq;
115 pcibios_disable_irq = &pci_visws_disable_irq;
116
110 pci_visws_init(); 117 pci_visws_init();
111 pcibios_init(); 118 pcibios_init();
119
120 return 0;
112} 121}
113subsys_initcall(pci_subsys_init); 122subsys_initcall(pci_subsys_init);