ia64/xen-unstable

changeset 4747:d8a9ad9290ac

bitkeeper revision 1.1389.1.34 (42778a6aQ30Jj7E2TxzCF9ZtVpGMtw)

Move PCI device scanning to dom0. Enable ACPI in dom0. This should greatly
reduce the complexity of xen and move the complexity of dealing with
hardware bugs and workarounds etc to dom0.

The ioapic local apic (and hence all the vectors) are owned by the hypervisor.
Dom0 enables the ACPI interpreter, handles PCI and ACPI based interrupt
routing.

New hypercalls to assign vectors and for accessing the ioapic.

Functionality not yet provided:

o acpi=off to support machines with broken or no acpi support.
o support for driver domains

Signed-off-by: Arun Sharma <arun.sharma@intel.com>
Signed-off-by: Asit Mallick <asit.k.mallick@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue May 03 14:27:54 2005 +0000 (2005-05-03)
parents 3ddafa92ae74
children 9c9be1b0e3b1 abf7ff0997cc 28ca42d843d8
files .rootkeys linux-2.6.11-xen-sparse/arch/xen/Kconfig linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile linux-2.6.11-xen-sparse/arch/xen/i386/kernel/acpi/Makefile linux-2.6.11-xen-sparse/arch/xen/i386/kernel/acpi/boot.c linux-2.6.11-xen-sparse/arch/xen/i386/kernel/apic.c linux-2.6.11-xen-sparse/arch/xen/i386/kernel/io_apic.c linux-2.6.11-xen-sparse/arch/xen/i386/kernel/mpparse.c linux-2.6.11-xen-sparse/arch/xen/i386/pci/Makefile linux-2.6.11-xen-sparse/arch/xen/i386/pci/direct.c linux-2.6.11-xen-sparse/arch/xen/i386/pci/irq.c linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig linux-2.6.11-xen-sparse/drivers/acpi/tables.c linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/fixmap.h linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io_apic.h linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h xen/Rules.mk xen/arch/x86/Makefile xen/arch/x86/io_apic.c xen/common/physdev.c xen/drivers/Makefile xen/include/asm-x86/config.h xen/include/asm-x86/io_apic.h xen/include/public/physdev.h
line diff
     1.1 --- a/.rootkeys	Tue May 03 12:28:27 2005 +0000
     1.2 +++ b/.rootkeys	Tue May 03 14:27:54 2005 +0000
     1.3 @@ -220,6 +220,9 @@ 424f001dsBzCezYZD8vAn-h5D9ZRtQ linux-2.6
     1.4  40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig
     1.5  40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.11-xen-sparse/arch/xen/i386/Makefile
     1.6  40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile
     1.7 +42778a68_kGyflDnRbar9WAmb4CKYw linux-2.6.11-xen-sparse/arch/xen/i386/kernel/acpi/Makefile
     1.8 +42778a68_2OruSz7lwFPBiGhl3y-FA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/acpi/boot.c
     1.9 +42778a69h76S5SCnDonnxnIt9nDGFQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/apic.c
    1.10  40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/Makefile
    1.11  40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/common.c
    1.12  41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile
    1.13 @@ -227,10 +230,12 @@ 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6
    1.14  40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/entry.S
    1.15  40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.11-xen-sparse/arch/xen/i386/kernel/head.S
    1.16  40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
    1.17 +42778a69_lodTzZVlojib1-pZF030g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/io_apic.c
    1.18  40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c
    1.19  41d00d82zN8IfLBRxc7G_i7lbwT3cQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c
    1.20  40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ldt.c
    1.21  41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/microcode.c
    1.22 +42778a69obEqvR75wSKCWPk9QnHo-w linux-2.6.11-xen-sparse/arch/xen/i386/kernel/mpparse.c
    1.23  4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/pci-dma.c
    1.24  40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
    1.25  40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/setup.c
    1.26 @@ -251,7 +256,6 @@ 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6
    1.27  41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.11-xen-sparse/arch/xen/i386/mm/ioremap.c
    1.28  40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.11-xen-sparse/arch/xen/i386/mm/pgtable.c
    1.29  4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.11-xen-sparse/arch/xen/i386/pci/Makefile
    1.30 -4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.11-xen-sparse/arch/xen/i386/pci/direct.c
    1.31  4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.11-xen-sparse/arch/xen/i386/pci/irq.c
    1.32  40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.11-xen-sparse/arch/xen/kernel/Makefile
    1.33  40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c
    1.34 @@ -296,6 +300,7 @@ 424efaa6uMX8YJASAVJT8ral74dz9Q linux-2.6
    1.35  424efaa629XgfZi3vvTAuQmhCqmvIA linux-2.6.11-xen-sparse/arch/xen/x86_64/pci/Makefile
    1.36  424efaa64SRL9FZhtQovFJAVh9sZlQ linux-2.6.11-xen-sparse/arch/xen/x86_64/pci/Makefile-BUS
    1.37  41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.11-xen-sparse/drivers/Makefile
    1.38 +42778a69QJ93x9p93ALrTV5QELHF-Q linux-2.6.11-xen-sparse/drivers/acpi/tables.c
    1.39  4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.11-xen-sparse/drivers/char/mem.c
    1.40  4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.11-xen-sparse/drivers/char/tty_io.c
    1.41  40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.11-xen-sparse/drivers/xen/Makefile
    1.42 @@ -347,6 +352,7 @@ 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6
    1.43  4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/highmem.h
    1.44  42539fb5A9hsS3NFQ-2VY4y1TONZZQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h
    1.45  40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io.h
    1.46 +42778a69MXZVxch4pQqYsMPS0WnNSg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io_apic.h
    1.47  40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
    1.48  40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
    1.49  40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
     2.1 --- a/linux-2.6.11-xen-sparse/arch/xen/Kconfig	Tue May 03 12:28:27 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/Kconfig	Tue May 03 14:27:54 2005 +0000
     2.3 @@ -181,6 +181,12 @@ endmenu
     2.4  
     2.5  source "arch/xen/Kconfig.drivers"
     2.6  
     2.7 +if XEN_PRIVILEGED_GUEST
     2.8 +menu "Power management options"
     2.9 +source "drivers/acpi/Kconfig"
    2.10 +endmenu
    2.11 +endif
    2.12 +
    2.13  source "fs/Kconfig"
    2.14  
    2.15  source "security/Kconfig"
     3.1 --- a/linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32	Tue May 03 12:28:27 2005 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32	Tue May 03 14:27:54 2005 +0000
     3.3 @@ -133,12 +133,23 @@ CONFIG_NOHIGHMEM=y
     3.4  CONFIG_MTRR=y
     3.5  CONFIG_HAVE_DEC_LOCK=y
     3.6  # CONFIG_REGPARM is not set
     3.7 +CONFIG_X86_LOCAL_APIC=y
     3.8 +CONFIG_X86_IO_APIC=y
     3.9  
    3.10  #
    3.11  # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
    3.12  #
    3.13 +CONFIG_X86_UP_APIC=y
    3.14 +CONFIG_X86_UP_IOAPIC=y
    3.15  CONFIG_PCI=y
    3.16 +# CONFIG_PCI_GOBIOS is not set
    3.17 +# CONFIG_PCI_GOMMCONFIG is not set
    3.18 +# CONFIG_PCI_GODIRECT is not set
    3.19 +CONFIG_PCI_GOANY=y
    3.20 +CONFIG_PCI_BIOS=y
    3.21  CONFIG_PCI_DIRECT=y
    3.22 +# CONFIG_PCIEPORTBUS is not set
    3.23 +# CONFIG_PCI_MSI is not set
    3.24  CONFIG_PCI_LEGACY_PROC=y
    3.25  # CONFIG_PCI_NAMES is not set
    3.26  CONFIG_ISA=y
    3.27 @@ -176,6 +187,8 @@ CONFIG_MAGIC_SYSRQ=y
    3.28  # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
    3.29  # CONFIG_FRAME_POINTER is not set
    3.30  # CONFIG_4KSTACKS is not set
    3.31 +CONFIG_X86_FIND_SMP_CONFIG=y
    3.32 +CONFIG_X86_MPPARSE=y
    3.33  CONFIG_GENERIC_HARDIRQS=y
    3.34  CONFIG_GENERIC_IRQ_PROBE=y
    3.35  CONFIG_X86_BIOS_REBOOT=y
    3.36 @@ -842,6 +855,7 @@ CONFIG_DRM_MGA=m
    3.37  CONFIG_DRM_SIS=m
    3.38  # CONFIG_MWAVE is not set
    3.39  # CONFIG_RAW_DRIVER is not set
    3.40 +# CONFIG_HPET is not set
    3.41  # CONFIG_HANGCHECK_TIMER is not set
    3.42  
    3.43  #
    3.44 @@ -1008,6 +1022,37 @@ CONFIG_USB_HIDINPUT=y
    3.45  # CONFIG_INFINIBAND is not set
    3.46  
    3.47  #
    3.48 +# Power management options
    3.49 +#
    3.50 +
    3.51 +#
    3.52 +# ACPI (Advanced Configuration and Power Interface) Support
    3.53 +#
    3.54 +CONFIG_ACPI=y
    3.55 +CONFIG_ACPI_BOOT=y
    3.56 +CONFIG_ACPI_INTERPRETER=y
    3.57 +CONFIG_ACPI_AC=m
    3.58 +CONFIG_ACPI_BATTERY=m
    3.59 +CONFIG_ACPI_BUTTON=m
    3.60 +CONFIG_ACPI_VIDEO=m
    3.61 +CONFIG_ACPI_FAN=m
    3.62 +CONFIG_ACPI_PROCESSOR=m
    3.63 +CONFIG_ACPI_THERMAL=m
    3.64 +CONFIG_ACPI_ASUS=m
    3.65 +CONFIG_ACPI_IBM=m
    3.66 +CONFIG_ACPI_TOSHIBA=m
    3.67 +# CONFIG_ACPI_CUSTOM_DSDT is not set
    3.68 +CONFIG_ACPI_BLACKLIST_YEAR=0
    3.69 +# CONFIG_ACPI_DEBUG is not set
    3.70 +CONFIG_ACPI_BUS=y
    3.71 +CONFIG_ACPI_EC=y
    3.72 +CONFIG_ACPI_POWER=y
    3.73 +CONFIG_ACPI_PCI=y
    3.74 +CONFIG_ACPI_SYSTEM=y
    3.75 +# CONFIG_X86_PM_TIMER is not set
    3.76 +# CONFIG_ACPI_CONTAINER is not set
    3.77 +
    3.78 +#
    3.79  # File systems
    3.80  #
    3.81  CONFIG_EXT2_FS=y
     4.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig	Tue May 03 12:28:27 2005 +0000
     4.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig	Tue May 03 14:27:54 2005 +0000
     4.3 @@ -662,11 +662,15 @@ config REGPARM
     4.4  	generate incorrect output with certain kernel constructs when
     4.5  	-mregparm=3 is used.
     4.6  
     4.7 -
     4.8  config X86_LOCAL_APIC
     4.9  	bool
    4.10 -	depends on (X86_VISWS || SMP) && !X86_VOYAGER
    4.11 -	default n
    4.12 +	depends on !SMP && X86_UP_APIC
    4.13 +	default y
    4.14 +
    4.15 +config X86_IO_APIC
    4.16 +	bool
    4.17 +	depends on !SMP && X86_UP_IOAPIC
    4.18 +	default y
    4.19  
    4.20  if XEN_PHYSDEV_ACCESS
    4.21  
    4.22 @@ -677,10 +681,45 @@ config X86_VISWS_APIC
    4.23  	depends on X86_VISWS
    4.24  	default y
    4.25  
    4.26 -#config X86_IO_APIC
    4.27 -#	bool
    4.28 -#	depends on SMP && !(X86_VISWS || X86_VOYAGER)
    4.29 -#	default y
    4.30 +config X86_LOCAL_APIC
    4.31 +	bool
    4.32 +	depends on (X86_VISWS || SMP) && !X86_VOYAGER
    4.33 +	default y
    4.34 +
    4.35 +config X86_UP_APIC
    4.36 +	bool "Local APIC support on uniprocessors" if !SMP
    4.37 +	depends on !(X86_VISWS || X86_VOYAGER)
    4.38 +	---help---
    4.39 +	  A local APIC (Advanced Programmable Interrupt Controller) is an
    4.40 +	  integrated interrupt controller in the CPU. If you have a single-CPU
    4.41 +	  system which has a processor with a local APIC, you can say Y here to
    4.42 +	  enable and use it. If you say Y here even though your machine doesn't
    4.43 +	  have a local APIC, then the kernel will still run with no slowdown at
    4.44 +	  all. The local APIC supports CPU-generated self-interrupts (timer,
    4.45 +	  performance counters), and the NMI watchdog which detects hard
    4.46 +	  lockups.
    4.47 +
    4.48 +	  If you have a system with several CPUs, you do not need to say Y
    4.49 +	  here: the local APIC will be used automatically.
    4.50 +
    4.51 +config X86_UP_IOAPIC
    4.52 +	bool "IO-APIC support on uniprocessors"
    4.53 +	depends on !SMP && X86_UP_APIC
    4.54 +	help
    4.55 +	  An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an
    4.56 +	  SMP-capable replacement for PC-style interrupt controllers. Most
    4.57 +	  SMP systems and a small number of uniprocessor systems have one.
    4.58 +	  If you have a single-CPU system with an IO-APIC, you can say Y here
    4.59 +	  to use it. If you say Y here even though your machine doesn't have
    4.60 +	  an IO-APIC, then the kernel will still run with no slowdown at all.
    4.61 +
    4.62 +	  If you have a system with several CPUs, you do not need to say Y
    4.63 +	  here: the IO-APIC will be used automatically.
    4.64 +
    4.65 +config X86_IO_APIC
    4.66 +	bool
    4.67 +	depends on SMP && !(X86_VISWS || X86_VOYAGER)
    4.68 +	default y
    4.69  
    4.70  config PCI
    4.71  	bool "PCI support" if !X86_VISWS
    4.72 @@ -697,52 +736,47 @@ config PCI
    4.73  	  information about which PCI hardware does work under Linux and which
    4.74  	  doesn't.
    4.75  
    4.76 -#choice
    4.77 -#	prompt "PCI access mode"
    4.78 -#	depends on PCI && !X86_VISWS
    4.79 -#	default PCI_GOANY
    4.80 -#	---help---
    4.81 -#	  On PCI systems, the BIOS can be used to detect the PCI devices and
    4.82 -#	  determine their configuration. However, some old PCI motherboards
    4.83 -#	  have BIOS bugs and may crash if this is done. Also, some embedded
    4.84 -#	  PCI-based systems don't have any BIOS at all. Linux can also try to
    4.85 -#	  detect the PCI hardware directly without using the BIOS.
    4.86 -#
    4.87 -#	  With this option, you can specify how Linux should detect the
    4.88 -#	  PCI devices. If you choose "BIOS", the BIOS will be used,
    4.89 -#	  if you choose "Direct", the BIOS won't be used, and if you
    4.90 -#	  choose "MMConfig", then PCI Express MMCONFIG will be used.
    4.91 -#	  If you choose "Any", the kernel will try MMCONFIG, then the
    4.92 -#	  direct access method and falls back to the BIOS if that doesn't
    4.93 -#	  work. If unsure, go with the default, which is "Any".
    4.94 -#
    4.95 -#config PCI_GOBIOS
    4.96 -#	bool "BIOS"
    4.97 -#
    4.98 -#config PCI_GOMMCONFIG
    4.99 -#	bool "MMConfig"
   4.100 -#
   4.101 -#config PCI_GODIRECT
   4.102 -#	bool "Direct"
   4.103 -#
   4.104 -#config PCI_GOANY
   4.105 -#	bool "Any"
   4.106 -#
   4.107 -#endchoice
   4.108 -#
   4.109 -#config PCI_BIOS
   4.110 -#	bool
   4.111 -#	depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
   4.112 -#	default y
   4.113 -#
   4.114 -#config PCI_DIRECT
   4.115 -#	bool
   4.116 -# 	depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
   4.117 -#	default y
   4.118 +choice
   4.119 +	prompt "PCI access mode"
   4.120 +	depends on PCI && !X86_VISWS
   4.121 +	default PCI_GOANY
   4.122 +	---help---
   4.123 +	  On PCI systems, the BIOS can be used to detect the PCI devices and
   4.124 +	  determine their configuration. However, some old PCI motherboards
   4.125 +	  have BIOS bugs and may crash if this is done. Also, some embedded
   4.126 +	  PCI-based systems don't have any BIOS at all. Linux can also try to
   4.127 +	  detect the PCI hardware directly without using the BIOS.
   4.128 +
   4.129 +	  With this option, you can specify how Linux should detect the
   4.130 +	  PCI devices. If you choose "BIOS", the BIOS will be used,
   4.131 +	  if you choose "Direct", the BIOS won't be used, and if you
   4.132 +	  choose "MMConfig", then PCI Express MMCONFIG will be used.
   4.133 +	  If you choose "Any", the kernel will try MMCONFIG, then the
   4.134 +	  direct access method and falls back to the BIOS if that doesn't
   4.135 +	  work. If unsure, go with the default, which is "Any".
   4.136 +
   4.137 +config PCI_GOBIOS
   4.138 +	bool "BIOS"
   4.139 +
   4.140 +config PCI_GOMMCONFIG
   4.141 +	bool "MMConfig"
   4.142 +
   4.143 +config PCI_GODIRECT
   4.144 +	bool "Direct"
   4.145 +
   4.146 +config PCI_GOANY
   4.147 +	bool "Any"
   4.148 +
   4.149 +endchoice
   4.150 +
   4.151 +config PCI_BIOS
   4.152 +	bool
   4.153 +	depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
   4.154 +	default n
   4.155  
   4.156  config PCI_DIRECT
   4.157  	bool
   4.158 - 	depends on PCI
   4.159 + 	depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
   4.160  	default y
   4.161  
   4.162  source "drivers/pci/pcie/Kconfig"
   4.163 @@ -927,7 +961,7 @@ config 4KSTACKS
   4.164  config X86_FIND_SMP_CONFIG
   4.165  	bool
   4.166  	depends on X86_LOCAL_APIC || X86_VOYAGER
   4.167 -	default y
   4.168 +	default n
   4.169  
   4.170  config X86_MPPARSE
   4.171  	bool
     5.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile	Tue May 03 12:28:27 2005 +0000
     5.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile	Tue May 03 14:27:54 2005 +0000
     5.3 @@ -30,7 +30,7 @@ c-obj-$(CONFIG_APM)		+= apm.o
     5.4  obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o
     5.5  #obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
     5.6  c-obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
     5.7 -#obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
     5.8 +obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
     5.9  c-obj-$(CONFIG_X86_LOCAL_APIC)	+= nmi.o
    5.10  c-obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
    5.11  c-obj-$(CONFIG_X86_NUMAQ)	+= numaq.o
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/acpi/Makefile	Tue May 03 14:27:54 2005 +0000
     6.3 @@ -0,0 +1,9 @@
     6.4 +obj-$(CONFIG_ACPI_BOOT)		        := boot.o
     6.5 +c-obj-$(CONFIG_X86_IO_APIC)	        += earlyquirk.o
     6.6 +c-obj-$(CONFIG_ACPI_SLEEP)	        += sleep.o wakeup.o
     6.7 +
     6.8 +c-link                                  :=
     6.9 +
    6.10 +$(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-link)):
    6.11 +	@ln -fsn $(srctree)/arch/i386/kernel/acpi/$(notdir $@) $@
    6.12 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/acpi/boot.c	Tue May 03 14:27:54 2005 +0000
     7.3 @@ -0,0 +1,926 @@
     7.4 +/*
     7.5 + *  boot.c - Architecture-Specific Low-Level ACPI Boot Support
     7.6 + *
     7.7 + *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
     7.8 + *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
     7.9 + *
    7.10 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    7.11 + *
    7.12 + *  This program is free software; you can redistribute it and/or modify
    7.13 + *  it under the terms of the GNU General Public License as published by
    7.14 + *  the Free Software Foundation; either version 2 of the License, or
    7.15 + *  (at your option) any later version.
    7.16 + *
    7.17 + *  This program is distributed in the hope that it will be useful,
    7.18 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.19 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.20 + *  GNU General Public License for more details.
    7.21 + *
    7.22 + *  You should have received a copy of the GNU General Public License
    7.23 + *  along with this program; if not, write to the Free Software
    7.24 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.25 + *
    7.26 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    7.27 + */
    7.28 +
    7.29 +#include <linux/init.h>
    7.30 +#include <linux/config.h>
    7.31 +#include <linux/acpi.h>
    7.32 +#include <linux/efi.h>
    7.33 +#include <linux/irq.h>
    7.34 +#include <linux/module.h>
    7.35 +
    7.36 +#include <asm/pgtable.h>
    7.37 +#include <asm/io_apic.h>
    7.38 +#include <asm/apic.h>
    7.39 +#include <asm/io.h>
    7.40 +#include <asm/irq.h>
    7.41 +#include <asm/mpspec.h>
    7.42 +#ifdef CONFIG_XEN
    7.43 +#include <asm/fixmap.h>
    7.44 +#endif
    7.45 +
    7.46 +void (*pm_power_off)(void) = NULL;
    7.47 +
    7.48 +#ifdef	CONFIG_X86_64
    7.49 +
    7.50 +static inline void  acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
    7.51 +extern void __init clustered_apic_check(void);
    7.52 +static inline int ioapic_setup_disabled(void) { return 0; }
    7.53 +#include <asm/proto.h>
    7.54 +
    7.55 +#else	/* X86 */
    7.56 +
    7.57 +#ifdef	CONFIG_X86_LOCAL_APIC
    7.58 +#include <mach_apic.h>
    7.59 +#include <mach_mpparse.h>
    7.60 +#endif	/* CONFIG_X86_LOCAL_APIC */
    7.61 +
    7.62 +#endif	/* X86 */
    7.63 +
    7.64 +#define BAD_MADT_ENTRY(entry, end) (					    \
    7.65 +		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
    7.66 +		((acpi_table_entry_header *)entry)->length != sizeof(*entry))
    7.67 +
    7.68 +#define PREFIX			"ACPI: "
    7.69 +
    7.70 +#ifdef CONFIG_ACPI_PCI
    7.71 +int acpi_noirq __initdata;	/* skip ACPI IRQ initialization */
    7.72 +int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
    7.73 +#else
    7.74 +int acpi_noirq __initdata = 1;
    7.75 +int acpi_pci_disabled __initdata = 1;
    7.76 +#endif
    7.77 +int acpi_ht __initdata = 1;	/* enable HT */
    7.78 +
    7.79 +int acpi_lapic;
    7.80 +int acpi_ioapic;
    7.81 +int acpi_strict;
    7.82 +EXPORT_SYMBOL(acpi_strict);
    7.83 +
    7.84 +acpi_interrupt_flags acpi_sci_flags __initdata;
    7.85 +int acpi_sci_override_gsi __initdata;
    7.86 +int acpi_skip_timer_override __initdata;
    7.87 +
    7.88 +#ifdef CONFIG_X86_LOCAL_APIC
    7.89 +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
    7.90 +#endif
    7.91 +
    7.92 +#ifndef __HAVE_ARCH_CMPXCHG
    7.93 +#warning ACPI uses CMPXCHG, i486 and later hardware
    7.94 +#endif
    7.95 +
    7.96 +#define MAX_MADT_ENTRIES	256
    7.97 +u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
    7.98 +			{ [0 ... MAX_MADT_ENTRIES-1] = 0xff };
    7.99 +EXPORT_SYMBOL(x86_acpiid_to_apicid);
   7.100 +
   7.101 +/* --------------------------------------------------------------------------
   7.102 +                              Boot-time Configuration
   7.103 +   -------------------------------------------------------------------------- */
   7.104 +
   7.105 +/*
   7.106 + * The default interrupt routing model is PIC (8259).  This gets
   7.107 + * overriden if IOAPICs are enumerated (below).
   7.108 + */
   7.109 +enum acpi_irq_model_id		acpi_irq_model = ACPI_IRQ_MODEL_PIC;
   7.110 +
   7.111 +#ifdef CONFIG_XEN
   7.112 +
   7.113 +char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
   7.114 +{
   7.115 +        unsigned int i,j;
   7.116 +
   7.117 +        j = PAGE_ALIGN(size) >> PAGE_SHIFT;
   7.118 +        for (i = 0; (i < FIX_ACPI_PAGES) && j ; i++, j--) {
   7.119 +                __set_fixmap_ma(FIX_ACPI_END - i,
   7.120 +                                (phys_addr & PAGE_MASK) + (i << PAGE_SHIFT),
   7.121 +                                PAGE_KERNEL);
   7.122 +        }
   7.123 +
   7.124 +        return (char *) __fix_to_virt(FIX_ACPI_END) + (phys_addr & ~PAGE_MASK);
   7.125 +}
   7.126 +#else
   7.127 +#ifdef	CONFIG_X86_64
   7.128 +
   7.129 +/* rely on all ACPI tables being in the direct mapping */
   7.130 +char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
   7.131 +{
   7.132 +	if (!phys_addr || !size)
   7.133 +	return NULL;
   7.134 +
   7.135 +	if (phys_addr < (end_pfn_map << PAGE_SHIFT))
   7.136 +		return __va(phys_addr);
   7.137 +
   7.138 +	return NULL;
   7.139 +}
   7.140 +
   7.141 +#else
   7.142 +
   7.143 +/*
   7.144 + * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
   7.145 + * to map the target physical address. The problem is that set_fixmap()
   7.146 + * provides a single page, and it is possible that the page is not
   7.147 + * sufficient.
   7.148 + * By using this area, we can map up to MAX_IO_APICS pages temporarily,
   7.149 + * i.e. until the next __va_range() call.
   7.150 + *
   7.151 + * Important Safety Note:  The fixed I/O APIC page numbers are *subtracted*
   7.152 + * from the fixed base.  That's why we start at FIX_IO_APIC_BASE_END and
   7.153 + * count idx down while incrementing the phys address.
   7.154 + */
   7.155 +char *__acpi_map_table(unsigned long phys, unsigned long size)
   7.156 +{
   7.157 +	unsigned long base, offset, mapped_size;
   7.158 +	int idx;
   7.159 +
   7.160 +	if (phys + size < 8*1024*1024) 
   7.161 +		return __va(phys); 
   7.162 +
   7.163 +	offset = phys & (PAGE_SIZE - 1);
   7.164 +	mapped_size = PAGE_SIZE - offset;
   7.165 +	set_fixmap(FIX_ACPI_END, phys);
   7.166 +	base = fix_to_virt(FIX_ACPI_END);
   7.167 +
   7.168 +	/*
   7.169 +	 * Most cases can be covered by the below.
   7.170 +	 */
   7.171 +	idx = FIX_ACPI_END;
   7.172 +	while (mapped_size < size) {
   7.173 +		if (--idx < FIX_ACPI_BEGIN)
   7.174 +			return NULL;	/* cannot handle this */
   7.175 +		phys += PAGE_SIZE;
   7.176 +		set_fixmap(idx, phys);
   7.177 +		mapped_size += PAGE_SIZE;
   7.178 +	}
   7.179 +
   7.180 +	return ((unsigned char *) base + offset);
   7.181 +}
   7.182 +#endif
   7.183 +#endif /* CONFIG_XEN */
   7.184 +
   7.185 +#ifdef CONFIG_PCI_MMCONFIG
   7.186 +static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
   7.187 +{
   7.188 +	struct acpi_table_mcfg *mcfg;
   7.189 +
   7.190 +	if (!phys_addr || !size)
   7.191 +		return -EINVAL;
   7.192 +
   7.193 +	mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size);
   7.194 +	if (!mcfg) {
   7.195 +		printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
   7.196 +		return -ENODEV;
   7.197 +	}
   7.198 +
   7.199 +	if (mcfg->base_reserved) {
   7.200 +		printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
   7.201 +		return -ENODEV;
   7.202 +	}
   7.203 +
   7.204 +	pci_mmcfg_base_addr = mcfg->base_address;
   7.205 +
   7.206 +	return 0;
   7.207 +}
   7.208 +#else
   7.209 +#define	acpi_parse_mcfg NULL
   7.210 +#endif /* !CONFIG_PCI_MMCONFIG */
   7.211 +
   7.212 +#ifdef CONFIG_X86_LOCAL_APIC
   7.213 +static int __init
   7.214 +acpi_parse_madt (
   7.215 +	unsigned long		phys_addr,
   7.216 +	unsigned long		size)
   7.217 +{
   7.218 +	struct acpi_table_madt	*madt = NULL;
   7.219 +
   7.220 +	if (!phys_addr || !size)
   7.221 +		return -EINVAL;
   7.222 +
   7.223 +	madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
   7.224 +	if (!madt) {
   7.225 +		printk(KERN_WARNING PREFIX "Unable to map MADT\n");
   7.226 +		return -ENODEV;
   7.227 +	}
   7.228 +
   7.229 +	if (madt->lapic_address) {
   7.230 +		acpi_lapic_addr = (u64) madt->lapic_address;
   7.231 +
   7.232 +		printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
   7.233 +			madt->lapic_address);
   7.234 +	}
   7.235 +
   7.236 +	acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
   7.237 +	
   7.238 +	return 0;
   7.239 +}
   7.240 +
   7.241 +
   7.242 +static int __init
   7.243 +acpi_parse_lapic (
   7.244 +	acpi_table_entry_header *header, const unsigned long end)
   7.245 +{
   7.246 +	struct acpi_table_lapic	*processor = NULL;
   7.247 +
   7.248 +	processor = (struct acpi_table_lapic*) header;
   7.249 +
   7.250 +	if (BAD_MADT_ENTRY(processor, end))
   7.251 +		return -EINVAL;
   7.252 +
   7.253 +	acpi_table_print_madt_entry(header);
   7.254 +
   7.255 +	/* no utility in registering a disabled processor */
   7.256 +	if (processor->flags.enabled == 0)
   7.257 +		return 0;
   7.258 +
   7.259 +	x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
   7.260 +
   7.261 +	mp_register_lapic (
   7.262 +		processor->id,					   /* APIC ID */
   7.263 +		processor->flags.enabled);			  /* Enabled? */
   7.264 +
   7.265 +	return 0;
   7.266 +}
   7.267 +
   7.268 +static int __init
   7.269 +acpi_parse_lapic_addr_ovr (
   7.270 +	acpi_table_entry_header *header, const unsigned long end)
   7.271 +{
   7.272 +	struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
   7.273 +
   7.274 +	lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
   7.275 +
   7.276 +	if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
   7.277 +		return -EINVAL;
   7.278 +
   7.279 +	acpi_lapic_addr = lapic_addr_ovr->address;
   7.280 +
   7.281 +	return 0;
   7.282 +}
   7.283 +
   7.284 +static int __init
   7.285 +acpi_parse_lapic_nmi (
   7.286 +	acpi_table_entry_header *header, const unsigned long end)
   7.287 +{
   7.288 +	struct acpi_table_lapic_nmi *lapic_nmi = NULL;
   7.289 +
   7.290 +	lapic_nmi = (struct acpi_table_lapic_nmi*) header;
   7.291 +
   7.292 +	if (BAD_MADT_ENTRY(lapic_nmi, end))
   7.293 +		return -EINVAL;
   7.294 +
   7.295 +	acpi_table_print_madt_entry(header);
   7.296 +
   7.297 +	if (lapic_nmi->lint != 1)
   7.298 +		printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
   7.299 +
   7.300 +	return 0;
   7.301 +}
   7.302 +
   7.303 +
   7.304 +#endif /*CONFIG_X86_LOCAL_APIC*/
   7.305 +
   7.306 +#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
   7.307 +
   7.308 +static int __init
   7.309 +acpi_parse_ioapic (
   7.310 +	acpi_table_entry_header *header, const unsigned long end)
   7.311 +{
   7.312 +	struct acpi_table_ioapic *ioapic = NULL;
   7.313 +
   7.314 +	ioapic = (struct acpi_table_ioapic*) header;
   7.315 +
   7.316 +	if (BAD_MADT_ENTRY(ioapic, end))
   7.317 +		return -EINVAL;
   7.318 + 
   7.319 +	acpi_table_print_madt_entry(header);
   7.320 +
   7.321 +	mp_register_ioapic (
   7.322 +		ioapic->id,
   7.323 +		ioapic->address,
   7.324 +		ioapic->global_irq_base);
   7.325 + 
   7.326 +	return 0;
   7.327 +}
   7.328 +
   7.329 +/*
   7.330 + * Parse Interrupt Source Override for the ACPI SCI
   7.331 + */
   7.332 +static void
   7.333 +acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
   7.334 +{
   7.335 +	if (trigger == 0)	/* compatible SCI trigger is level */
   7.336 +		trigger = 3;
   7.337 +
   7.338 +	if (polarity == 0)	/* compatible SCI polarity is low */
   7.339 +		polarity = 3;
   7.340 +
   7.341 +	/* Command-line over-ride via acpi_sci= */
   7.342 +	if (acpi_sci_flags.trigger)
   7.343 +		trigger = acpi_sci_flags.trigger;
   7.344 +
   7.345 +	if (acpi_sci_flags.polarity)
   7.346 +		polarity = acpi_sci_flags.polarity;
   7.347 +
   7.348 +	/*
   7.349 + 	 * mp_config_acpi_legacy_irqs() already setup IRQs < 16
   7.350 +	 * If GSI is < 16, this will update its flags,
   7.351 +	 * else it will create a new mp_irqs[] entry.
   7.352 +	 */
   7.353 +	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
   7.354 +
   7.355 +	/*
   7.356 +	 * stash over-ride to indicate we've been here
   7.357 +	 * and for later update of acpi_fadt
   7.358 +	 */
   7.359 +	acpi_sci_override_gsi = gsi;
   7.360 +	return;
   7.361 +}
   7.362 +
   7.363 +static int __init
   7.364 +acpi_parse_int_src_ovr (
   7.365 +	acpi_table_entry_header *header, const unsigned long end)
   7.366 +{
   7.367 +	struct acpi_table_int_src_ovr *intsrc = NULL;
   7.368 +
   7.369 +	intsrc = (struct acpi_table_int_src_ovr*) header;
   7.370 +
   7.371 +	if (BAD_MADT_ENTRY(intsrc, end))
   7.372 +		return -EINVAL;
   7.373 +
   7.374 +	acpi_table_print_madt_entry(header);
   7.375 +
   7.376 +	if (intsrc->bus_irq == acpi_fadt.sci_int) {
   7.377 +		acpi_sci_ioapic_setup(intsrc->global_irq,
   7.378 +			intsrc->flags.polarity, intsrc->flags.trigger);
   7.379 +		return 0;
   7.380 +	}
   7.381 +
   7.382 +	if (acpi_skip_timer_override &&
   7.383 +		intsrc->bus_irq == 0 && intsrc->global_irq == 2) {
   7.384 +			printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
   7.385 +			return 0;
   7.386 +	}
   7.387 +
   7.388 +	mp_override_legacy_irq (
   7.389 +		intsrc->bus_irq,
   7.390 +		intsrc->flags.polarity,
   7.391 +		intsrc->flags.trigger,
   7.392 +		intsrc->global_irq);
   7.393 +
   7.394 +	return 0;
   7.395 +}
   7.396 +
   7.397 +
   7.398 +static int __init
   7.399 +acpi_parse_nmi_src (
   7.400 +	acpi_table_entry_header *header, const unsigned long end)
   7.401 +{
   7.402 +	struct acpi_table_nmi_src *nmi_src = NULL;
   7.403 +
   7.404 +	nmi_src = (struct acpi_table_nmi_src*) header;
   7.405 +
   7.406 +	if (BAD_MADT_ENTRY(nmi_src, end))
   7.407 +		return -EINVAL;
   7.408 +
   7.409 +	acpi_table_print_madt_entry(header);
   7.410 +
   7.411 +	/* TBD: Support nimsrc entries? */
   7.412 +
   7.413 +	return 0;
   7.414 +}
   7.415 +
   7.416 +#endif /* CONFIG_X86_IO_APIC */
   7.417 +
   7.418 +#ifdef	CONFIG_ACPI_BUS
   7.419 +
   7.420 +/*
   7.421 + * acpi_pic_sci_set_trigger()
   7.422 + * 
   7.423 + * use ELCR to set PIC-mode trigger type for SCI
   7.424 + *
   7.425 + * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
   7.426 + * it may require Edge Trigger -- use "acpi_sci=edge"
   7.427 + *
   7.428 + * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
   7.429 + * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
   7.430 + * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
   7.431 + * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
   7.432 + */
   7.433 +
   7.434 +void __init
   7.435 +acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
   7.436 +{
   7.437 +	unsigned int mask = 1 << irq;
   7.438 +	unsigned int old, new;
   7.439 +
   7.440 +	/* Real old ELCR mask */
   7.441 +	old = inb(0x4d0) | (inb(0x4d1) << 8);
   7.442 +
   7.443 +	/*
   7.444 +	 * If we use ACPI to set PCI irq's, then we should clear ELCR
   7.445 +	 * since we will set it correctly as we enable the PCI irq
   7.446 +	 * routing.
   7.447 +	 */
   7.448 +	new = acpi_noirq ? old : 0;
   7.449 +
   7.450 +	/*
   7.451 +	 * Update SCI information in the ELCR, it isn't in the PCI
   7.452 +	 * routing tables..
   7.453 +	 */
   7.454 +	switch (trigger) {
   7.455 +	case 1:	/* Edge - clear */
   7.456 +		new &= ~mask;
   7.457 +		break;
   7.458 +	case 3: /* Level - set */
   7.459 +		new |= mask;
   7.460 +		break;
   7.461 +	}
   7.462 +
   7.463 +	if (old == new)
   7.464 +		return;
   7.465 +
   7.466 +	printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old);
   7.467 +	outb(new, 0x4d0);
   7.468 +	outb(new >> 8, 0x4d1);
   7.469 +}
   7.470 +
   7.471 +
   7.472 +#endif /* CONFIG_ACPI_BUS */
   7.473 +
   7.474 +int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
   7.475 +{
   7.476 +#ifdef CONFIG_X86_IO_APIC
   7.477 +	if (use_pci_vector() && !platform_legacy_irq(gsi))
   7.478 + 		*irq = IO_APIC_VECTOR(gsi);
   7.479 +	else
   7.480 +#endif
   7.481 +		*irq = gsi;
   7.482 +	return 0;
   7.483 +}
   7.484 +
   7.485 +unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
   7.486 +{
   7.487 +	unsigned int irq;
   7.488 +	unsigned int plat_gsi = gsi;
   7.489 +
   7.490 +#ifdef CONFIG_X86_IO_APIC
   7.491 +	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
   7.492 +		plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low);
   7.493 +	}
   7.494 +#endif
   7.495 +	acpi_gsi_to_irq(plat_gsi, &irq);
   7.496 +	return irq;
   7.497 +}
   7.498 +EXPORT_SYMBOL(acpi_register_gsi);
   7.499 +
   7.500 +/*
   7.501 + *  ACPI based hotplug support for CPU
   7.502 + */
   7.503 +#ifdef CONFIG_ACPI_HOTPLUG_CPU
   7.504 +int
   7.505 +acpi_map_lsapic(acpi_handle handle, int *pcpu)
   7.506 +{
   7.507 +	/* TBD */
   7.508 +	return -EINVAL;
   7.509 +}
   7.510 +EXPORT_SYMBOL(acpi_map_lsapic);
   7.511 +
   7.512 +
   7.513 +int
   7.514 +acpi_unmap_lsapic(int cpu)
   7.515 +{
   7.516 +	/* TBD */
   7.517 +	return -EINVAL;
   7.518 +}
   7.519 +EXPORT_SYMBOL(acpi_unmap_lsapic);
   7.520 +#endif /* CONFIG_ACPI_HOTPLUG_CPU */
   7.521 +
   7.522 +static unsigned long __init
   7.523 +acpi_scan_rsdp (
   7.524 +	unsigned long		start,
   7.525 +	unsigned long		length)
   7.526 +{
   7.527 +	unsigned long		offset = 0;
   7.528 +	unsigned long		sig_len = sizeof("RSD PTR ") - 1;
   7.529 +        unsigned long           vstart = isa_bus_to_virt(start);
   7.530 +
   7.531 +	/*
   7.532 +	 * Scan all 16-byte boundaries of the physical memory region for the
   7.533 +	 * RSDP signature.
   7.534 +	 */
   7.535 +	for (offset = 0; offset < length; offset += 16) {
   7.536 +		if (strncmp((char *) (vstart + offset), "RSD PTR ", sig_len))
   7.537 +			continue;
   7.538 +		return (start + offset);
   7.539 +	}
   7.540 +
   7.541 +	return 0;
   7.542 +}
   7.543 +
   7.544 +static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
   7.545 +{
   7.546 +	struct acpi_table_sbf *sb;
   7.547 +
   7.548 +	if (!phys_addr || !size)
   7.549 +	return -EINVAL;
   7.550 +
   7.551 +	sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size);
   7.552 +	if (!sb) {
   7.553 +		printk(KERN_WARNING PREFIX "Unable to map SBF\n");
   7.554 +		return -ENODEV;
   7.555 +	}
   7.556 +
   7.557 +	sbf_port = sb->sbf_cmos; /* Save CMOS port */
   7.558 +
   7.559 +	return 0;
   7.560 +}
   7.561 +
   7.562 +
   7.563 +#ifdef CONFIG_HPET_TIMER
   7.564 +
   7.565 +static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
   7.566 +{
   7.567 +	struct acpi_table_hpet *hpet_tbl;
   7.568 +
   7.569 +	if (!phys || !size)
   7.570 +		return -EINVAL;
   7.571 +
   7.572 +	hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size);
   7.573 +	if (!hpet_tbl) {
   7.574 +		printk(KERN_WARNING PREFIX "Unable to map HPET\n");
   7.575 +		return -ENODEV;
   7.576 +	}
   7.577 +
   7.578 +	if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) {
   7.579 +		printk(KERN_WARNING PREFIX "HPET timers must be located in "
   7.580 +		       "memory.\n");
   7.581 +		return -1;
   7.582 +	}
   7.583 +
   7.584 +#ifdef	CONFIG_X86_64
   7.585 +        vxtime.hpet_address = hpet_tbl->addr.addrl |
   7.586 +                ((long) hpet_tbl->addr.addrh << 32);
   7.587 +
   7.588 +        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
   7.589 +               hpet_tbl->id, vxtime.hpet_address);
   7.590 +#else	/* X86 */
   7.591 +	{
   7.592 +		extern unsigned long hpet_address;
   7.593 +
   7.594 +		hpet_address = hpet_tbl->addr.addrl;
   7.595 +		printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
   7.596 +			hpet_tbl->id, hpet_address);
   7.597 +	}
   7.598 +#endif	/* X86 */
   7.599 +
   7.600 +	return 0;
   7.601 +}
   7.602 +#else
   7.603 +#define	acpi_parse_hpet	NULL
   7.604 +#endif
   7.605 +
   7.606 +#ifdef CONFIG_X86_PM_TIMER
   7.607 +extern u32 pmtmr_ioport;
   7.608 +#endif
   7.609 +
   7.610 +static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
   7.611 +{
   7.612 +	struct fadt_descriptor_rev2 *fadt = NULL;
   7.613 +
   7.614 +	fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
   7.615 +	if(!fadt) {
   7.616 +		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
   7.617 +		return 0;
   7.618 +	}
   7.619 +
   7.620 +#ifdef	CONFIG_ACPI_INTERPRETER
   7.621 +	/* initialize sci_int early for INT_SRC_OVR MADT parsing */
   7.622 +	acpi_fadt.sci_int = fadt->sci_int;
   7.623 +#endif
   7.624 +
   7.625 +#ifdef CONFIG_X86_PM_TIMER
   7.626 +	/* detect the location of the ACPI PM Timer */
   7.627 +	if (fadt->revision >= FADT2_REVISION_ID) {
   7.628 +		/* FADT rev. 2 */
   7.629 +		if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
   7.630 +			return 0;
   7.631 +
   7.632 +		pmtmr_ioport = fadt->xpm_tmr_blk.address;
   7.633 +	} else {
   7.634 +		/* FADT rev. 1 */
   7.635 +		pmtmr_ioport = fadt->V1_pm_tmr_blk;
   7.636 +	}
   7.637 +	if (pmtmr_ioport)
   7.638 +		printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
   7.639 +#endif
   7.640 +	return 0;
   7.641 +}
   7.642 +
   7.643 +
   7.644 +unsigned long __init
   7.645 +acpi_find_rsdp (void)
   7.646 +{
   7.647 +	unsigned long		rsdp_phys = 0;
   7.648 +
   7.649 +	if (efi_enabled) {
   7.650 +		if (efi.acpi20)
   7.651 +			return __pa(efi.acpi20);
   7.652 +		else if (efi.acpi)
   7.653 +			return __pa(efi.acpi);
   7.654 +	}
   7.655 +
   7.656 +	/*
   7.657 +	 * Scan memory looking for the RSDP signature. First search EBDA (low
   7.658 +	 * memory) paragraphs and then search upper memory (E0000-FFFFF).
   7.659 +	 */
   7.660 +	rsdp_phys = acpi_scan_rsdp (0, 0x400);
   7.661 +	if (!rsdp_phys)
   7.662 +		rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
   7.663 +
   7.664 +        __set_fixmap_ma(FIX_ACPI_RSDP_PAGE, rsdp_phys, PAGE_KERNEL);
   7.665 +
   7.666 +	return rsdp_phys;
   7.667 +}
   7.668 +
   7.669 +#ifdef	CONFIG_X86_LOCAL_APIC
   7.670 +/*
   7.671 + * Parse LAPIC entries in MADT
   7.672 + * returns 0 on success, < 0 on error
   7.673 + */
   7.674 +static int __init
   7.675 +acpi_parse_madt_lapic_entries(void)
   7.676 +{
   7.677 +	int count;
   7.678 +
   7.679 +#ifdef CONFIG_XEN
   7.680 +        return 0;
   7.681 +#endif
   7.682 +
   7.683 +	/* 
   7.684 +	 * Note that the LAPIC address is obtained from the MADT (32-bit value)
   7.685 +	 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
   7.686 +	 */
   7.687 +
   7.688 +	count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0);
   7.689 +	if (count < 0) {
   7.690 +		printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
   7.691 +		return count;
   7.692 +	}
   7.693 +
   7.694 +	mp_register_lapic_address(acpi_lapic_addr);
   7.695 +
   7.696 +	count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
   7.697 +				       MAX_APICS);
   7.698 +	if (!count) { 
   7.699 +		printk(KERN_ERR PREFIX "No LAPIC entries present\n");
   7.700 +		/* TBD: Cleanup to allow fallback to MPS */
   7.701 +		return -ENODEV;
   7.702 +	}
   7.703 +	else if (count < 0) {
   7.704 +		printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
   7.705 +		/* TBD: Cleanup to allow fallback to MPS */
   7.706 +		return count;
   7.707 +	}
   7.708 +
   7.709 +	count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
   7.710 +	if (count < 0) {
   7.711 +		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
   7.712 +		/* TBD: Cleanup to allow fallback to MPS */
   7.713 +		return count;
   7.714 +	}
   7.715 +	return 0;
   7.716 +}
   7.717 +#endif /* CONFIG_X86_LOCAL_APIC */
   7.718 +
   7.719 +#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
   7.720 +/*
   7.721 + * Parse IOAPIC related entries in MADT
   7.722 + * returns 0 on success, < 0 on error
   7.723 + */
   7.724 +static int __init
   7.725 +acpi_parse_madt_ioapic_entries(void)
   7.726 +{
   7.727 +	int count;
   7.728 +
   7.729 +	/*
   7.730 +	 * ACPI interpreter is required to complete interrupt setup,
   7.731 +	 * so if it is off, don't enumerate the io-apics with ACPI.
   7.732 +	 * If MPS is present, it will handle them,
   7.733 +	 * otherwise the system will stay in PIC mode
   7.734 +	 */
   7.735 +	if (acpi_disabled || acpi_noirq) {
   7.736 +		return -ENODEV;
   7.737 +        }
   7.738 +
   7.739 +	/*
   7.740 + 	 * if "noapic" boot option, don't look for IO-APICs
   7.741 +	 */
   7.742 +	if (skip_ioapic_setup) {
   7.743 +		printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
   7.744 +			"due to 'noapic' option.\n");
   7.745 +		return -ENODEV;
   7.746 +	}
   7.747 +
   7.748 +	count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS);
   7.749 +	if (!count) {
   7.750 +		printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
   7.751 +		return -ENODEV;
   7.752 +	}
   7.753 +	else if (count < 0) {
   7.754 +		printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
   7.755 +		return count;
   7.756 +	}
   7.757 +
   7.758 +	count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
   7.759 +	if (count < 0) {
   7.760 +		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
   7.761 +		/* TBD: Cleanup to allow fallback to MPS */
   7.762 +		return count;
   7.763 +	}
   7.764 +
   7.765 +	/*
   7.766 +	 * If BIOS did not supply an INT_SRC_OVR for the SCI
   7.767 +	 * pretend we got one so we can set the SCI flags.
   7.768 +	 */
   7.769 +	if (!acpi_sci_override_gsi)
   7.770 +		acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
   7.771 +
   7.772 +	/* Fill in identity legacy mapings where no override */
   7.773 +	mp_config_acpi_legacy_irqs();
   7.774 +
   7.775 +	count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
   7.776 +	if (count < 0) {
   7.777 +		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
   7.778 +		/* TBD: Cleanup to allow fallback to MPS */
   7.779 +		return count;
   7.780 +	}
   7.781 +
   7.782 +	return 0;
   7.783 +}
   7.784 +#else
   7.785 +static inline int acpi_parse_madt_ioapic_entries(void)
   7.786 +{
   7.787 +	return -1;
   7.788 +}
   7.789 +#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */
   7.790 +
   7.791 +
   7.792 +static void __init
   7.793 +acpi_process_madt(void)
   7.794 +{
   7.795 +#ifdef CONFIG_X86_LOCAL_APIC
   7.796 +	int count, error;
   7.797 +
   7.798 +	count = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
   7.799 +	if (count >= 1) {
   7.800 +
   7.801 +		/*
   7.802 +		 * Parse MADT LAPIC entries
   7.803 +		 */
   7.804 +		error = acpi_parse_madt_lapic_entries();
   7.805 +		if (!error) {
   7.806 +			acpi_lapic = 1;
   7.807 +
   7.808 +			/*
   7.809 +			 * Parse MADT IO-APIC entries
   7.810 +			 */
   7.811 +			error = acpi_parse_madt_ioapic_entries();
   7.812 +			if (!error) {
   7.813 +				acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
   7.814 +				acpi_irq_balance_set(NULL);
   7.815 +				acpi_ioapic = 1;
   7.816 +
   7.817 +				smp_found_config = 1;
   7.818 +				clustered_apic_check();
   7.819 +			}
   7.820 +		}
   7.821 +		if (error == -EINVAL) {
   7.822 +			/*
   7.823 +			 * Dell Precision Workstation 410, 610 come here.
   7.824 +			 */
   7.825 +			printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n");
   7.826 +			disable_acpi();
   7.827 +		}
   7.828 +	}
   7.829 +#endif
   7.830 +	return;
   7.831 +}
   7.832 +
   7.833 +/*
   7.834 + * acpi_boot_table_init() and acpi_boot_init()
   7.835 + *  called from setup_arch(), always.
   7.836 + *	1. checksums all tables
   7.837 + *	2. enumerates lapics
   7.838 + *	3. enumerates io-apics
   7.839 + *
   7.840 + * acpi_table_init() is separate to allow reading SRAT without
   7.841 + * other side effects.
   7.842 + *
   7.843 + * side effects of acpi_boot_init:
   7.844 + *	acpi_lapic = 1 if LAPIC found
   7.845 + *	acpi_ioapic = 1 if IOAPIC found
   7.846 + *	if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
   7.847 + *	if acpi_blacklisted() acpi_disabled = 1;
   7.848 + *	acpi_irq_model=...
   7.849 + *	...
   7.850 + *
   7.851 + * return value: (currently ignored)
   7.852 + *	0: success
   7.853 + *	!0: failure
   7.854 + */
   7.855 +
   7.856 +int __init
   7.857 +acpi_boot_table_init(void)
   7.858 +{
   7.859 +	int error;
   7.860 +
   7.861 +	/*
   7.862 +	 * If acpi_disabled, bail out
   7.863 +	 * One exception: acpi=ht continues far enough to enumerate LAPICs
   7.864 +	 */
   7.865 +	if (acpi_disabled && !acpi_ht)
   7.866 +		 return 1;
   7.867 +
   7.868 +	/* 
   7.869 +	 * Initialize the ACPI boot-time table parser.
   7.870 +	 */
   7.871 +	error = acpi_table_init();
   7.872 +	if (error) {
   7.873 +		disable_acpi();
   7.874 +		return error;
   7.875 +	}
   7.876 +
   7.877 +#ifdef __i386__
   7.878 +	//check_acpi_pci();
   7.879 +#endif
   7.880 +
   7.881 +	acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
   7.882 +
   7.883 +	/*
   7.884 +	 * blacklist may disable ACPI entirely
   7.885 +	 */
   7.886 +	error = acpi_blacklisted();
   7.887 +	if (error) {
   7.888 +		extern int acpi_force;
   7.889 +
   7.890 +		if (acpi_force) {
   7.891 +			printk(KERN_WARNING PREFIX "acpi=force override\n");
   7.892 +		} else {
   7.893 +			printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
   7.894 +			disable_acpi();
   7.895 +			return error;
   7.896 +		}
   7.897 +	}
   7.898 +
   7.899 +	return 0;
   7.900 +}
   7.901 +
   7.902 +
   7.903 +int __init acpi_boot_init(void)
   7.904 +{
   7.905 +	/*
   7.906 +	 * If acpi_disabled, bail out
   7.907 +	 * One exception: acpi=ht continues far enough to enumerate LAPICs
   7.908 +	 */
   7.909 +	if (acpi_disabled && !acpi_ht)
   7.910 +		 return 1;
   7.911 +
   7.912 +	acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
   7.913 +
   7.914 +	/*
   7.915 +	 * set sci_int and PM timer address
   7.916 +	 */
   7.917 +	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
   7.918 +
   7.919 +	/*
   7.920 +	 * Process the Multiple APIC Description Table (MADT), if present
   7.921 +	 */
   7.922 +	acpi_process_madt();
   7.923 +
   7.924 +	acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
   7.925 +	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
   7.926 +
   7.927 +	return 0;
   7.928 +}
   7.929 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/apic.c	Tue May 03 14:27:54 2005 +0000
     8.3 @@ -0,0 +1,53 @@
     8.4 +/*
     8.5 + *	Local APIC handling, local APIC timers
     8.6 + *
     8.7 + *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
     8.8 + *
     8.9 + *	Fixes
    8.10 + *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
    8.11 + *					thanks to Eric Gilmore
    8.12 + *					and Rolf G. Tews
    8.13 + *					for testing these extensively.
    8.14 + *	Maciej W. Rozycki	:	Various updates and fixes.
    8.15 + *	Mikael Pettersson	:	Power Management for UP-APIC.
    8.16 + *	Pavel Machek and
    8.17 + *	Mikael Pettersson	:	PM converted to driver model.
    8.18 + */
    8.19 +
    8.20 +#include <linux/config.h>
    8.21 +#include <linux/init.h>
    8.22 +#include <asm/apic.h>
    8.23 +
    8.24 +int apic_verbosity;
    8.25 +
    8.26 +int get_physical_broadcast(void)
    8.27 +{
    8.28 +        return 0xff;
    8.29 +}
    8.30 +
    8.31 +/*
    8.32 + * 'what should we do if we get a hw irq event on an illegal vector'.
    8.33 + * each architecture has to answer this themselves.
    8.34 + */
    8.35 +void ack_bad_irq(unsigned int irq)
    8.36 +{
    8.37 +	printk("unexpected IRQ trap at vector %02x\n", irq);
    8.38 +	/*
    8.39 +	 * Currently unexpected vectors happen only on SMP and APIC.
    8.40 +	 * We _must_ ack these because every local APIC has only N
    8.41 +	 * irq slots per priority level, and a 'hanging, unacked' IRQ
    8.42 +	 * holds up an irq slot - in excessive cases (when multiple
    8.43 +	 * unexpected vectors occur) that might lock up the APIC
    8.44 +	 * completely.
    8.45 +	 */
    8.46 +	ack_APIC_irq();
    8.47 +}
    8.48 +
    8.49 +/*
    8.50 + * This initializes the IO-APIC and APIC hardware if this is
    8.51 + * a UP kernel.
    8.52 + */
    8.53 +int __init APIC_init_uniprocessor (void)
    8.54 +{
    8.55 +	return 0;
    8.56 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/io_apic.c	Tue May 03 14:27:54 2005 +0000
     9.3 @@ -0,0 +1,394 @@
     9.4 +/*
     9.5 + *	Intel IO-APIC support for multi-Pentium hosts.
     9.6 + *
     9.7 + *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
     9.8 + *
     9.9 + *	Many thanks to Stig Venaas for trying out countless experimental
    9.10 + *	patches and reporting/debugging problems patiently!
    9.11 + *
    9.12 + *	(c) 1999, Multiple IO-APIC support, developed by
    9.13 + *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
    9.14 + *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
    9.15 + *	further tested and cleaned up by Zach Brown <zab@redhat.com>
    9.16 + *	and Ingo Molnar <mingo@redhat.com>
    9.17 + *
    9.18 + *	Fixes
    9.19 + *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
    9.20 + *					thanks to Eric Gilmore
    9.21 + *					and Rolf G. Tews
    9.22 + *					for testing these extensively
    9.23 + *	Paul Diefenbaugh	:	Added full ACPI support
    9.24 + */
    9.25 +
    9.26 +#include <linux/mm.h>
    9.27 +#include <linux/irq.h>
    9.28 +#include <linux/interrupt.h>
    9.29 +#include <linux/init.h>
    9.30 +#include <linux/delay.h>
    9.31 +#include <linux/sched.h>
    9.32 +#include <linux/config.h>
    9.33 +#include <linux/smp_lock.h>
    9.34 +#include <linux/mc146818rtc.h>
    9.35 +#include <linux/compiler.h>
    9.36 +#include <linux/acpi.h>
    9.37 +
    9.38 +#include <linux/sysdev.h>
    9.39 +#include <asm/io.h>
    9.40 +#include <asm/smp.h>
    9.41 +#include <asm/desc.h>
    9.42 +#include <asm/timer.h>
    9.43 +#include <asm/io_apic.h>
    9.44 +#include <asm/apic.h>
    9.45 +
    9.46 +#include <mach_apic.h>
    9.47 +
    9.48 +#include "io_ports.h"
    9.49 +
    9.50 +int (*ioapic_renumber_irq)(int ioapic, int irq);
    9.51 +atomic_t irq_mis_count;
    9.52 +
    9.53 +unsigned long io_apic_irqs;
    9.54 +int skip_ioapic_setup;
    9.55 +
    9.56 +static DEFINE_SPINLOCK(ioapic_lock);
    9.57 +
    9.58 +/*
    9.59 + *	Is the SiS APIC rmw bug present ?
    9.60 + *	-1 = don't know, 0 = no, 1 = yes
    9.61 + */
    9.62 +int sis_apic_bug = -1;
    9.63 +
    9.64 +/*
    9.65 + * # of IRQ routing registers
    9.66 + */
    9.67 +int nr_ioapic_registers[MAX_IO_APICS];
    9.68 +
    9.69 +/*
    9.70 + * Rough estimation of how many shared IRQs there are, can
    9.71 + * be changed anytime.
    9.72 + */
    9.73 +#define MAX_PLUS_SHARED_IRQS NR_IRQS
    9.74 +#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
    9.75 +
    9.76 +/*
    9.77 + * This is performance-critical, we want to do it O(1)
    9.78 + *
    9.79 + * the indexing order of this array favors 1:1 mappings
    9.80 + * between pins and IRQs.
    9.81 + */
    9.82 +
    9.83 +static struct irq_pin_list {
    9.84 +	int apic, pin, next;
    9.85 +} irq_2_pin[PIN_MAP_SIZE];
    9.86 +
    9.87 +int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
    9.88 +#ifdef CONFIG_PCI_MSI
    9.89 +#define vector_to_irq(vector) 	\
    9.90 +	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
    9.91 +#else
    9.92 +#define vector_to_irq(vector)	(vector)
    9.93 +#endif
    9.94 +
    9.95 +
    9.96 +#ifndef CONFIG_SMP
    9.97 +void fastcall send_IPI_self(int vector)
    9.98 +{
    9.99 +     return; 
   9.100 +}
   9.101 +#endif
   9.102 +
   9.103 +int irqbalance_disable(char *str)
   9.104 +{
   9.105 +     return 0; 
   9.106 +}
   9.107 +
   9.108 +void print_IO_APIC(void)
   9.109 +{
   9.110 +     return; 
   9.111 +}
   9.112 +
   9.113 +/*
   9.114 + * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
   9.115 + * shared ISA-space IRQs, so we have to support them. We are super
   9.116 + * fast in the common case, and fast for shared ISA-space IRQs.
   9.117 + */
   9.118 +static void add_pin_to_irq(unsigned int irq, int apic, int pin)
   9.119 +{
   9.120 +	static int first_free_entry = NR_IRQS;
   9.121 +	struct irq_pin_list *entry = irq_2_pin + irq;
   9.122 +
   9.123 +	while (entry->next)
   9.124 +		entry = irq_2_pin + entry->next;
   9.125 +
   9.126 +	if (entry->pin != -1) {
   9.127 +		entry->next = first_free_entry;
   9.128 +		entry = irq_2_pin + entry->next;
   9.129 +		if (++first_free_entry >= PIN_MAP_SIZE)
   9.130 +			panic("io_apic.c: whoops");
   9.131 +	}
   9.132 +	entry->apic = apic;
   9.133 +	entry->pin = pin;
   9.134 +}
   9.135 +
   9.136 +/*
   9.137 + * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
   9.138 + * specific CPU-side IRQs.
   9.139 + */
   9.140 +
   9.141 +#define MAX_PIRQS 8
   9.142 +int pirq_entries [MAX_PIRQS];
   9.143 +int pirqs_enabled;
   9.144 +/*
   9.145 + * Find a specific PCI IRQ entry.
   9.146 + * Not an __init, possibly needed by modules
   9.147 + */
   9.148 +static int pin_2_irq(int idx, int apic, int pin);
   9.149 +
   9.150 +int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
   9.151 +{
   9.152 +	int apic, i, best_guess = -1;
   9.153 +
   9.154 +	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
   9.155 +		"slot:%d, pin:%d.\n", bus, slot, pin);
   9.156 +	if (mp_bus_id_to_pci_bus[bus] == -1) {
   9.157 +		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
   9.158 +		return -1;
   9.159 +	}
   9.160 +	for (i = 0; i < mp_irq_entries; i++) {
   9.161 +		int lbus = mp_irqs[i].mpc_srcbus;
   9.162 +
   9.163 +		for (apic = 0; apic < nr_ioapics; apic++)
   9.164 +			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
   9.165 +			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
   9.166 +				break;
   9.167 +
   9.168 +		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
   9.169 +		    !mp_irqs[i].mpc_irqtype &&
   9.170 +		    (bus == lbus) &&
   9.171 +		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
   9.172 +			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
   9.173 +
   9.174 +			if (!(apic || IO_APIC_IRQ(irq)))
   9.175 +				continue;
   9.176 +
   9.177 +			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
   9.178 +				return irq;
   9.179 +			/*
   9.180 +			 * Use the first all-but-pin matching entry as a
   9.181 +			 * best-guess fuzzy result for broken mptables.
   9.182 +			 */
   9.183 +			if (best_guess < 0)
   9.184 +				best_guess = irq;
   9.185 +		}
   9.186 +	}
   9.187 +	return best_guess;
   9.188 +}
   9.189 +
   9.190 +static int pin_2_irq(int idx, int apic, int pin)
   9.191 +{
   9.192 +	int irq, i;
   9.193 +	int bus = mp_irqs[idx].mpc_srcbus;
   9.194 +
   9.195 +	/*
   9.196 +	 * Debugging check, we are in big trouble if this message pops up!
   9.197 +	 */
   9.198 +	if (mp_irqs[idx].mpc_dstirq != pin)
   9.199 +		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
   9.200 +
   9.201 +	switch (mp_bus_id_to_type[bus])
   9.202 +	{
   9.203 +		case MP_BUS_ISA: /* ISA pin */
   9.204 +		case MP_BUS_EISA:
   9.205 +		case MP_BUS_MCA:
   9.206 +		case MP_BUS_NEC98:
   9.207 +		{
   9.208 +			irq = mp_irqs[idx].mpc_srcbusirq;
   9.209 +			break;
   9.210 +		}
   9.211 +		case MP_BUS_PCI: /* PCI pin */
   9.212 +		{
   9.213 +			/*
   9.214 +			 * PCI IRQs are mapped in order
   9.215 +			 */
   9.216 +			i = irq = 0;
   9.217 +			while (i < apic)
   9.218 +				irq += nr_ioapic_registers[i++];
   9.219 +			irq += pin;
   9.220 +
   9.221 +			/*
   9.222 +			 * For MPS mode, so far only needed by ES7000 platform
   9.223 +			 */
   9.224 +			if (ioapic_renumber_irq)
   9.225 +				irq = ioapic_renumber_irq(apic, irq);
   9.226 +
   9.227 +			break;
   9.228 +		}
   9.229 +		default:
   9.230 +		{
   9.231 +			printk(KERN_ERR "unknown bus type %d.\n",bus); 
   9.232 +			irq = 0;
   9.233 +			break;
   9.234 +		}
   9.235 +	}
   9.236 +
   9.237 +	/*
   9.238 +	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
   9.239 +	 */
   9.240 +	if ((pin >= 16) && (pin <= 23)) {
   9.241 +		if (pirq_entries[pin-16] != -1) {
   9.242 +			if (!pirq_entries[pin-16]) {
   9.243 +				apic_printk(APIC_VERBOSE, KERN_DEBUG
   9.244 +						"disabling PIRQ%d\n", pin-16);
   9.245 +			} else {
   9.246 +				irq = pirq_entries[pin-16];
   9.247 +				apic_printk(APIC_VERBOSE, KERN_DEBUG
   9.248 +						"using PIRQ%d -> IRQ %d\n",
   9.249 +						pin-16, irq);
   9.250 +			}
   9.251 +		}
   9.252 +	}
   9.253 +	return irq;
   9.254 +}
   9.255 +
   9.256 +/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
   9.257 +u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
   9.258 +
   9.259 +int assign_irq_vector(int irq)
   9.260 +{
   9.261 +	static int current_vector = FIRST_DEVICE_VECTOR;
   9.262 +        physdev_op_t op;
   9.263 +        int ret;
   9.264 +
   9.265 +	BUG_ON(irq >= NR_IRQ_VECTORS);
   9.266 +	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
   9.267 +		return IO_APIC_VECTOR(irq);
   9.268 +
   9.269 +        op.cmd = PHYSDEVOP_ASSIGN_VECTOR;
   9.270 +        op.u.irq_op.irq = irq;
   9.271 +        ret = HYPERVISOR_physdev_op(&op);
   9.272 +        if (ret)
   9.273 +            return -ENOSPC;
   9.274 +
   9.275 +        current_vector = op.u.irq_op.vector;
   9.276 +	vector_irq[current_vector] = irq;
   9.277 +	if (irq != AUTO_ASSIGN)
   9.278 +		IO_APIC_VECTOR(irq) = current_vector;
   9.279 +
   9.280 +	return current_vector;
   9.281 +}
   9.282 +
   9.283 +#ifdef CONFIG_ACPI_BOOT
   9.284 +int __init io_apic_get_unique_id (int ioapic, int apic_id)
   9.285 +{
   9.286 +	union IO_APIC_reg_00 reg_00;
   9.287 +	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
   9.288 +	unsigned long flags;
   9.289 +
   9.290 +	/*
   9.291 +	 * The P4 platform supports up to 256 APIC IDs on two separate APIC 
   9.292 +	 * buses (one for LAPICs, one for IOAPICs), where predecessors only 
   9.293 +	 * supports up to 16 on one shared APIC bus.
   9.294 +	 * 
   9.295 +	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
   9.296 +	 *      advantage of new APIC bus architecture.
   9.297 +	 */
   9.298 +
   9.299 +	if (physids_empty(apic_id_map))
   9.300 +		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
   9.301 +
   9.302 +	spin_lock_irqsave(&ioapic_lock, flags);
   9.303 +	reg_00.raw = io_apic_read(ioapic, 0);
   9.304 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   9.305 +
   9.306 +	if (apic_id >= get_physical_broadcast()) {
   9.307 +		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
   9.308 +			"%d\n", ioapic, apic_id, reg_00.bits.ID);
   9.309 +		apic_id = reg_00.bits.ID;
   9.310 +	}
   9.311 +
   9.312 +	apic_printk(APIC_VERBOSE, KERN_INFO
   9.313 +			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
   9.314 +
   9.315 +	return apic_id;
   9.316 +}
   9.317 +
   9.318 +
   9.319 +int __init io_apic_get_version (int ioapic)
   9.320 +{
   9.321 +	union IO_APIC_reg_01	reg_01;
   9.322 +	unsigned long flags;
   9.323 +
   9.324 +	spin_lock_irqsave(&ioapic_lock, flags);
   9.325 +	reg_01.raw = io_apic_read(ioapic, 1);
   9.326 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   9.327 +
   9.328 +	return reg_01.bits.version;
   9.329 +}
   9.330 +
   9.331 +
   9.332 +int __init io_apic_get_redir_entries (int ioapic)
   9.333 +{
   9.334 +	union IO_APIC_reg_01	reg_01;
   9.335 +	unsigned long flags;
   9.336 +
   9.337 +	spin_lock_irqsave(&ioapic_lock, flags);
   9.338 +	reg_01.raw = io_apic_read(ioapic, 1);
   9.339 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   9.340 +
   9.341 +	return reg_01.bits.entries;
   9.342 +}
   9.343 +
   9.344 +int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
   9.345 +{
   9.346 +	struct IO_APIC_route_entry entry;
   9.347 +	unsigned long flags;
   9.348 +
   9.349 +	if (!IO_APIC_IRQ(irq)) {
   9.350 +		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
   9.351 +			ioapic);
   9.352 +		return -EINVAL;
   9.353 +	}
   9.354 +
   9.355 +	/*
   9.356 +	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
   9.357 +	 * Note that we mask (disable) IRQs now -- these get enabled when the
   9.358 +	 * corresponding device driver registers for this IRQ.
   9.359 +	 */
   9.360 +
   9.361 +	memset(&entry,0,sizeof(entry));
   9.362 +
   9.363 +	entry.delivery_mode = INT_DELIVERY_MODE;
   9.364 +	entry.dest_mode = INT_DEST_MODE;
   9.365 +	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
   9.366 +	entry.trigger = edge_level;
   9.367 +	entry.polarity = active_high_low;
   9.368 +	entry.mask  = 1;
   9.369 +
   9.370 +	/*
   9.371 +	 * IRQs < 16 are already in the irq_2_pin[] map
   9.372 +	 */
   9.373 +	if (irq >= 16)
   9.374 +		add_pin_to_irq(irq, ioapic, pin);
   9.375 +
   9.376 +	entry.vector = assign_irq_vector(irq);
   9.377 +
   9.378 +	apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
   9.379 +		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
   9.380 +		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
   9.381 +		edge_level, active_high_low);
   9.382 +
   9.383 +#ifndef CONFIG_XEN
   9.384 +	ioapic_register_intr(irq, entry.vector, edge_level);
   9.385 +
   9.386 +	if (!ioapic && (irq < 16))
   9.387 +		disable_8259A_irq(irq);
   9.388 +#endif
   9.389 +
   9.390 +	spin_lock_irqsave(&ioapic_lock, flags);
   9.391 +	io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
   9.392 +	io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
   9.393 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   9.394 +
   9.395 +	return 0;
   9.396 +}
   9.397 +#endif /*CONFIG_ACPI_BOOT*/
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/mpparse.c	Tue May 03 14:27:54 2005 +0000
    10.3 @@ -0,0 +1,1105 @@
    10.4 +/*
    10.5 + *	Intel Multiprocessor Specification 1.1 and 1.4
    10.6 + *	compliant MP-table parsing routines.
    10.7 + *
    10.8 + *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
    10.9 + *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
   10.10 + *
   10.11 + *	Fixes
   10.12 + *		Erich Boleyn	:	MP v1.4 and additional changes.
   10.13 + *		Alan Cox	:	Added EBDA scanning
   10.14 + *		Ingo Molnar	:	various cleanups and rewrites
   10.15 + *		Maciej W. Rozycki:	Bits for default MP configurations
   10.16 + *		Paul Diefenbaugh:	Added full ACPI support
   10.17 + */
   10.18 +
   10.19 +#include <linux/mm.h>
   10.20 +#include <linux/irq.h>
   10.21 +#include <linux/init.h>
   10.22 +#include <linux/acpi.h>
   10.23 +#include <linux/delay.h>
   10.24 +#include <linux/config.h>
   10.25 +#include <linux/bootmem.h>
   10.26 +#include <linux/smp_lock.h>
   10.27 +#include <linux/kernel_stat.h>
   10.28 +#include <linux/mc146818rtc.h>
   10.29 +#include <linux/bitops.h>
   10.30 +
   10.31 +#include <asm/smp.h>
   10.32 +#include <asm/acpi.h>
   10.33 +#include <asm/mtrr.h>
   10.34 +#include <asm/mpspec.h>
   10.35 +#include <asm/io_apic.h>
   10.36 +
   10.37 +#include <mach_apic.h>
   10.38 +#include <mach_mpparse.h>
   10.39 +#include <bios_ebda.h>
   10.40 +
   10.41 +/* Have we found an MP table */
   10.42 +int smp_found_config;
   10.43 +unsigned int __initdata maxcpus = NR_CPUS;
   10.44 +
   10.45 +/*
   10.46 + * Various Linux-internal data structures created from the
   10.47 + * MP-table.
   10.48 + */
   10.49 +int apic_version [MAX_APICS];
   10.50 +int mp_bus_id_to_type [MAX_MP_BUSSES];
   10.51 +int mp_bus_id_to_node [MAX_MP_BUSSES];
   10.52 +int mp_bus_id_to_local [MAX_MP_BUSSES];
   10.53 +int quad_local_to_mp_bus_id [NR_CPUS/4][4];
   10.54 +int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
   10.55 +int mp_current_pci_id;
   10.56 +
   10.57 +/* I/O APIC entries */
   10.58 +struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
   10.59 +
   10.60 +/* # of MP IRQ source entries */
   10.61 +struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
   10.62 +
   10.63 +/* MP IRQ source entries */
   10.64 +int mp_irq_entries;
   10.65 +
   10.66 +int nr_ioapics;
   10.67 +
   10.68 +int pic_mode;
   10.69 +unsigned long mp_lapic_addr;
   10.70 +
   10.71 +/* Processor that is doing the boot up */
   10.72 +unsigned int boot_cpu_physical_apicid = -1U;
   10.73 +unsigned int boot_cpu_logical_apicid = -1U;
   10.74 +/* Internal processor count */
   10.75 +static unsigned int __initdata num_processors;
   10.76 +
   10.77 +/* Bitmask of physically existing CPUs */
   10.78 +physid_mask_t phys_cpu_present_map;
   10.79 +
   10.80 +u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
   10.81 +
   10.82 +/*
   10.83 + * Intel MP BIOS table parsing routines:
   10.84 + */
   10.85 +
   10.86 +
   10.87 +/*
   10.88 + * Checksum an MP configuration block.
   10.89 + */
   10.90 +
   10.91 +static int __init mpf_checksum(unsigned char *mp, int len)
   10.92 +{
   10.93 +	int sum = 0;
   10.94 +
   10.95 +	while (len--)
   10.96 +		sum += *mp++;
   10.97 +
   10.98 +	return sum & 0xFF;
   10.99 +}
  10.100 +
  10.101 +/*
  10.102 + * Have to match translation table entries to main table entries by counter
  10.103 + * hence the mpc_record variable .... can't see a less disgusting way of
  10.104 + * doing this ....
  10.105 + */
  10.106 +
  10.107 +static int mpc_record; 
  10.108 +static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
  10.109 +
  10.110 +#ifdef CONFIG_X86_NUMAQ
  10.111 +static int MP_valid_apicid(int apicid, int version)
  10.112 +{
  10.113 +	return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
  10.114 +}
  10.115 +#else
  10.116 +static int MP_valid_apicid(int apicid, int version)
  10.117 +{
  10.118 +	if (version >= 0x14)
  10.119 +		return apicid < 0xff;
  10.120 +	else
  10.121 +		return apicid < 0xf;
  10.122 +}
  10.123 +#endif
  10.124 +
  10.125 +void __init MP_processor_info (struct mpc_config_processor *m)
  10.126 +{
  10.127 + 	int ver, apicid;
  10.128 +	physid_mask_t tmp;
  10.129 + 	
  10.130 +	if (!(m->mpc_cpuflag & CPU_ENABLED))
  10.131 +		return;
  10.132 +
  10.133 +	apicid = mpc_apic_id(m, translation_table[mpc_record]);
  10.134 +
  10.135 +	if (m->mpc_featureflag&(1<<0))
  10.136 +		Dprintk("    Floating point unit present.\n");
  10.137 +	if (m->mpc_featureflag&(1<<7))
  10.138 +		Dprintk("    Machine Exception supported.\n");
  10.139 +	if (m->mpc_featureflag&(1<<8))
  10.140 +		Dprintk("    64 bit compare & exchange supported.\n");
  10.141 +	if (m->mpc_featureflag&(1<<9))
  10.142 +		Dprintk("    Internal APIC present.\n");
  10.143 +	if (m->mpc_featureflag&(1<<11))
  10.144 +		Dprintk("    SEP present.\n");
  10.145 +	if (m->mpc_featureflag&(1<<12))
  10.146 +		Dprintk("    MTRR  present.\n");
  10.147 +	if (m->mpc_featureflag&(1<<13))
  10.148 +		Dprintk("    PGE  present.\n");
  10.149 +	if (m->mpc_featureflag&(1<<14))
  10.150 +		Dprintk("    MCA  present.\n");
  10.151 +	if (m->mpc_featureflag&(1<<15))
  10.152 +		Dprintk("    CMOV  present.\n");
  10.153 +	if (m->mpc_featureflag&(1<<16))
  10.154 +		Dprintk("    PAT  present.\n");
  10.155 +	if (m->mpc_featureflag&(1<<17))
  10.156 +		Dprintk("    PSE  present.\n");
  10.157 +	if (m->mpc_featureflag&(1<<18))
  10.158 +		Dprintk("    PSN  present.\n");
  10.159 +	if (m->mpc_featureflag&(1<<19))
  10.160 +		Dprintk("    Cache Line Flush Instruction present.\n");
  10.161 +	/* 20 Reserved */
  10.162 +	if (m->mpc_featureflag&(1<<21))
  10.163 +		Dprintk("    Debug Trace and EMON Store present.\n");
  10.164 +	if (m->mpc_featureflag&(1<<22))
  10.165 +		Dprintk("    ACPI Thermal Throttle Registers  present.\n");
  10.166 +	if (m->mpc_featureflag&(1<<23))
  10.167 +		Dprintk("    MMX  present.\n");
  10.168 +	if (m->mpc_featureflag&(1<<24))
  10.169 +		Dprintk("    FXSR  present.\n");
  10.170 +	if (m->mpc_featureflag&(1<<25))
  10.171 +		Dprintk("    XMM  present.\n");
  10.172 +	if (m->mpc_featureflag&(1<<26))
  10.173 +		Dprintk("    Willamette New Instructions  present.\n");
  10.174 +	if (m->mpc_featureflag&(1<<27))
  10.175 +		Dprintk("    Self Snoop  present.\n");
  10.176 +	if (m->mpc_featureflag&(1<<28))
  10.177 +		Dprintk("    HT  present.\n");
  10.178 +	if (m->mpc_featureflag&(1<<29))
  10.179 +		Dprintk("    Thermal Monitor present.\n");
  10.180 +	/* 30, 31 Reserved */
  10.181 +
  10.182 +
  10.183 +	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
  10.184 +		Dprintk("    Bootup CPU\n");
  10.185 +		boot_cpu_physical_apicid = m->mpc_apicid;
  10.186 +		boot_cpu_logical_apicid = apicid;
  10.187 +	}
  10.188 +
  10.189 +	if (num_processors >= NR_CPUS) {
  10.190 +		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
  10.191 +			"  Processor ignored.\n", NR_CPUS); 
  10.192 +		return;
  10.193 +	}
  10.194 +
  10.195 +	if (num_processors >= maxcpus) {
  10.196 +		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
  10.197 +			" Processor ignored.\n", maxcpus); 
  10.198 +		return;
  10.199 +	}
  10.200 +	num_processors++;
  10.201 +	ver = m->mpc_apicver;
  10.202 +
  10.203 +	if (!MP_valid_apicid(apicid, ver)) {
  10.204 +		printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
  10.205 +			m->mpc_apicid, MAX_APICS);
  10.206 +		--num_processors;
  10.207 +		return;
  10.208 +	}
  10.209 +
  10.210 +	tmp = apicid_to_cpu_present(apicid);
  10.211 +	physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
  10.212 +	
  10.213 +	/*
  10.214 +	 * Validate version
  10.215 +	 */
  10.216 +	if (ver == 0x0) {
  10.217 +		printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
  10.218 +		ver = 0x10;
  10.219 +	}
  10.220 +	apic_version[m->mpc_apicid] = ver;
  10.221 +	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
  10.222 +}
  10.223 +
  10.224 +static void __init MP_bus_info (struct mpc_config_bus *m)
  10.225 +{
  10.226 +	char str[7];
  10.227 +
  10.228 +	memcpy(str, m->mpc_bustype, 6);
  10.229 +	str[6] = 0;
  10.230 +
  10.231 +	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
  10.232 +
  10.233 +	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
  10.234 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
  10.235 +	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
  10.236 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
  10.237 +	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
  10.238 +		mpc_oem_pci_bus(m, translation_table[mpc_record]);
  10.239 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
  10.240 +		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
  10.241 +		mp_current_pci_id++;
  10.242 +	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
  10.243 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
  10.244 +	} else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
  10.245 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
  10.246 +	} else {
  10.247 +		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
  10.248 +	}
  10.249 +}
  10.250 +
  10.251 +static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
  10.252 +{
  10.253 +	if (!(m->mpc_flags & MPC_APIC_USABLE))
  10.254 +		return;
  10.255 +
  10.256 +	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n",
  10.257 +		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
  10.258 +	if (nr_ioapics >= MAX_IO_APICS) {
  10.259 +		printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
  10.260 +			MAX_IO_APICS, nr_ioapics);
  10.261 +		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
  10.262 +	}
  10.263 +	if (!m->mpc_apicaddr) {
  10.264 +		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
  10.265 +			" found in MP table, skipping!\n");
  10.266 +		return;
  10.267 +	}
  10.268 +	mp_ioapics[nr_ioapics] = *m;
  10.269 +	nr_ioapics++;
  10.270 +}
  10.271 +
  10.272 +static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
  10.273 +{
  10.274 +	mp_irqs [mp_irq_entries] = *m;
  10.275 +	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
  10.276 +		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
  10.277 +			m->mpc_irqtype, m->mpc_irqflag & 3,
  10.278 +			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
  10.279 +			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
  10.280 +	if (++mp_irq_entries == MAX_IRQ_SOURCES)
  10.281 +		panic("Max # of irq sources exceeded!!\n");
  10.282 +}
  10.283 +
  10.284 +static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
  10.285 +{
  10.286 +	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
  10.287 +		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
  10.288 +			m->mpc_irqtype, m->mpc_irqflag & 3,
  10.289 +			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
  10.290 +			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
  10.291 +	/*
  10.292 +	 * Well it seems all SMP boards in existence
  10.293 +	 * use ExtINT/LVT1 == LINT0 and
  10.294 +	 * NMI/LVT2 == LINT1 - the following check
  10.295 +	 * will show us if this assumptions is false.
  10.296 +	 * Until then we do not have to add baggage.
  10.297 +	 */
  10.298 +	if ((m->mpc_irqtype == mp_ExtINT) &&
  10.299 +		(m->mpc_destapiclint != 0))
  10.300 +			BUG();
  10.301 +	if ((m->mpc_irqtype == mp_NMI) &&
  10.302 +		(m->mpc_destapiclint != 1))
  10.303 +			BUG();
  10.304 +}
  10.305 +
  10.306 +#ifdef CONFIG_X86_NUMAQ
  10.307 +static void __init MP_translation_info (struct mpc_config_translation *m)
  10.308 +{
  10.309 +	printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
  10.310 +
  10.311 +	if (mpc_record >= MAX_MPC_ENTRY) 
  10.312 +		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
  10.313 +	else
  10.314 +		translation_table[mpc_record] = m; /* stash this for later */
  10.315 +	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
  10.316 +		node_set_online(m->trans_quad);
  10.317 +}
  10.318 +
  10.319 +/*
  10.320 + * Read/parse the MPC oem tables
  10.321 + */
  10.322 +
  10.323 +static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
  10.324 +	unsigned short oemsize)
  10.325 +{
  10.326 +	int count = sizeof (*oemtable); /* the header size */
  10.327 +	unsigned char *oemptr = ((unsigned char *)oemtable)+count;
  10.328 +	
  10.329 +	mpc_record = 0;
  10.330 +	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
  10.331 +	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
  10.332 +	{
  10.333 +		printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
  10.334 +			oemtable->oem_signature[0],
  10.335 +			oemtable->oem_signature[1],
  10.336 +			oemtable->oem_signature[2],
  10.337 +			oemtable->oem_signature[3]);
  10.338 +		return;
  10.339 +	}
  10.340 +	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
  10.341 +	{
  10.342 +		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
  10.343 +		return;
  10.344 +	}
  10.345 +	while (count < oemtable->oem_length) {
  10.346 +		switch (*oemptr) {
  10.347 +			case MP_TRANSLATION:
  10.348 +			{
  10.349 +				struct mpc_config_translation *m=
  10.350 +					(struct mpc_config_translation *)oemptr;
  10.351 +				MP_translation_info(m);
  10.352 +				oemptr += sizeof(*m);
  10.353 +				count += sizeof(*m);
  10.354 +				++mpc_record;
  10.355 +				break;
  10.356 +			}
  10.357 +			default:
  10.358 +			{
  10.359 +				printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
  10.360 +				return;
  10.361 +			}
  10.362 +		}
  10.363 +       }
  10.364 +}
  10.365 +
  10.366 +static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
  10.367 +		char *productid)
  10.368 +{
  10.369 +	if (strncmp(oem, "IBM NUMA", 8))
  10.370 +		printk("Warning!  May not be a NUMA-Q system!\n");
  10.371 +	if (mpc->mpc_oemptr)
  10.372 +		smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr,
  10.373 +				mpc->mpc_oemsize);
  10.374 +}
  10.375 +#endif	/* CONFIG_X86_NUMAQ */
  10.376 +
  10.377 +/*
  10.378 + * Read/parse the MPC
  10.379 + */
  10.380 +
  10.381 +static int __init smp_read_mpc(struct mp_config_table *mpc)
  10.382 +{
  10.383 +	char str[16];
  10.384 +	char oem[10];
  10.385 +	int count=sizeof(*mpc);
  10.386 +	unsigned char *mpt=((unsigned char *)mpc)+count;
  10.387 +
  10.388 +	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
  10.389 +		printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",
  10.390 +			*(u32 *)mpc->mpc_signature);
  10.391 +		return 0;
  10.392 +	}
  10.393 +	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
  10.394 +		printk(KERN_ERR "SMP mptable: checksum error!\n");
  10.395 +		return 0;
  10.396 +	}
  10.397 +	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
  10.398 +		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
  10.399 +			mpc->mpc_spec);
  10.400 +		return 0;
  10.401 +	}
  10.402 +	if (!mpc->mpc_lapic) {
  10.403 +		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
  10.404 +		return 0;
  10.405 +	}
  10.406 +	memcpy(oem,mpc->mpc_oem,8);
  10.407 +	oem[8]=0;
  10.408 +	printk(KERN_INFO "OEM ID: %s ",oem);
  10.409 +
  10.410 +	memcpy(str,mpc->mpc_productid,12);
  10.411 +	str[12]=0;
  10.412 +	printk("Product ID: %s ",str);
  10.413 +
  10.414 +	mps_oem_check(mpc, oem, str);
  10.415 +
  10.416 +	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
  10.417 +
  10.418 +	/* 
  10.419 +	 * Save the local APIC address (it might be non-default) -- but only
  10.420 +	 * if we're not using ACPI.
  10.421 +	 */
  10.422 +	if (!acpi_lapic)
  10.423 +		mp_lapic_addr = mpc->mpc_lapic;
  10.424 +
  10.425 +	/*
  10.426 +	 *	Now process the configuration blocks.
  10.427 +	 */
  10.428 +	mpc_record = 0;
  10.429 +	while (count < mpc->mpc_length) {
  10.430 +		switch(*mpt) {
  10.431 +			case MP_PROCESSOR:
  10.432 +			{
  10.433 +				struct mpc_config_processor *m=
  10.434 +					(struct mpc_config_processor *)mpt;
  10.435 +				/* ACPI may have already provided this data */
  10.436 +				if (!acpi_lapic)
  10.437 +					MP_processor_info(m);
  10.438 +				mpt += sizeof(*m);
  10.439 +				count += sizeof(*m);
  10.440 +				break;
  10.441 +			}
  10.442 +			case MP_BUS:
  10.443 +			{
  10.444 +				struct mpc_config_bus *m=
  10.445 +					(struct mpc_config_bus *)mpt;
  10.446 +				MP_bus_info(m);
  10.447 +				mpt += sizeof(*m);
  10.448 +				count += sizeof(*m);
  10.449 +				break;
  10.450 +			}
  10.451 +			case MP_IOAPIC:
  10.452 +			{
  10.453 +				struct mpc_config_ioapic *m=
  10.454 +					(struct mpc_config_ioapic *)mpt;
  10.455 +				MP_ioapic_info(m);
  10.456 +				mpt+=sizeof(*m);
  10.457 +				count+=sizeof(*m);
  10.458 +				break;
  10.459 +			}
  10.460 +			case MP_INTSRC:
  10.461 +			{
  10.462 +				struct mpc_config_intsrc *m=
  10.463 +					(struct mpc_config_intsrc *)mpt;
  10.464 +
  10.465 +				MP_intsrc_info(m);
  10.466 +				mpt+=sizeof(*m);
  10.467 +				count+=sizeof(*m);
  10.468 +				break;
  10.469 +			}
  10.470 +			case MP_LINTSRC:
  10.471 +			{
  10.472 +				struct mpc_config_lintsrc *m=
  10.473 +					(struct mpc_config_lintsrc *)mpt;
  10.474 +				MP_lintsrc_info(m);
  10.475 +				mpt+=sizeof(*m);
  10.476 +				count+=sizeof(*m);
  10.477 +				break;
  10.478 +			}
  10.479 +			default:
  10.480 +			{
  10.481 +				count = mpc->mpc_length;
  10.482 +				break;
  10.483 +			}
  10.484 +		}
  10.485 +		++mpc_record;
  10.486 +	}
  10.487 +	clustered_apic_check();
  10.488 +	if (!num_processors)
  10.489 +		printk(KERN_ERR "SMP mptable: no processors registered!\n");
  10.490 +	return num_processors;
  10.491 +}
  10.492 +
  10.493 +static int __init ELCR_trigger(unsigned int irq)
  10.494 +{
  10.495 +	unsigned int port;
  10.496 +
  10.497 +	port = 0x4d0 + (irq >> 3);
  10.498 +	return (inb(port) >> (irq & 7)) & 1;
  10.499 +}
  10.500 +
  10.501 +static void __init construct_default_ioirq_mptable(int mpc_default_type)
  10.502 +{
  10.503 +	struct mpc_config_intsrc intsrc;
  10.504 +	int i;
  10.505 +	int ELCR_fallback = 0;
  10.506 +
  10.507 +	intsrc.mpc_type = MP_INTSRC;
  10.508 +	intsrc.mpc_irqflag = 0;			/* conforming */
  10.509 +	intsrc.mpc_srcbus = 0;
  10.510 +	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
  10.511 +
  10.512 +	intsrc.mpc_irqtype = mp_INT;
  10.513 +
  10.514 +	/*
  10.515 +	 *  If true, we have an ISA/PCI system with no IRQ entries
  10.516 +	 *  in the MP table. To prevent the PCI interrupts from being set up
  10.517 +	 *  incorrectly, we try to use the ELCR. The sanity check to see if
  10.518 +	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
  10.519 +	 *  never be level sensitive, so we simply see if the ELCR agrees.
  10.520 +	 *  If it does, we assume it's valid.
  10.521 +	 */
  10.522 +	if (mpc_default_type == 5) {
  10.523 +		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
  10.524 +
  10.525 +		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
  10.526 +			printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
  10.527 +		else {
  10.528 +			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
  10.529 +			ELCR_fallback = 1;
  10.530 +		}
  10.531 +	}
  10.532 +
  10.533 +	for (i = 0; i < 16; i++) {
  10.534 +		switch (mpc_default_type) {
  10.535 +		case 2:
  10.536 +			if (i == 0 || i == 13)
  10.537 +				continue;	/* IRQ0 & IRQ13 not connected */
  10.538 +			/* fall through */
  10.539 +		default:
  10.540 +			if (i == 2)
  10.541 +				continue;	/* IRQ2 is never connected */
  10.542 +		}
  10.543 +
  10.544 +		if (ELCR_fallback) {
  10.545 +			/*
  10.546 +			 *  If the ELCR indicates a level-sensitive interrupt, we
  10.547 +			 *  copy that information over to the MP table in the
  10.548 +			 *  irqflag field (level sensitive, active high polarity).
  10.549 +			 */
  10.550 +			if (ELCR_trigger(i))
  10.551 +				intsrc.mpc_irqflag = 13;
  10.552 +			else
  10.553 +				intsrc.mpc_irqflag = 0;
  10.554 +		}
  10.555 +
  10.556 +		intsrc.mpc_srcbusirq = i;
  10.557 +		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
  10.558 +		MP_intsrc_info(&intsrc);
  10.559 +	}
  10.560 +
  10.561 +	intsrc.mpc_irqtype = mp_ExtINT;
  10.562 +	intsrc.mpc_srcbusirq = 0;
  10.563 +	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
  10.564 +	MP_intsrc_info(&intsrc);
  10.565 +}
  10.566 +
  10.567 +static inline void __init construct_default_ISA_mptable(int mpc_default_type)
  10.568 +{
  10.569 +	struct mpc_config_processor processor;
  10.570 +	struct mpc_config_bus bus;
  10.571 +	struct mpc_config_ioapic ioapic;
  10.572 +	struct mpc_config_lintsrc lintsrc;
  10.573 +	int linttypes[2] = { mp_ExtINT, mp_NMI };
  10.574 +	int i;
  10.575 +
  10.576 +	/*
  10.577 +	 * local APIC has default address
  10.578 +	 */
  10.579 +	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
  10.580 +
  10.581 +	/*
  10.582 +	 * 2 CPUs, numbered 0 & 1.
  10.583 +	 */
  10.584 +	processor.mpc_type = MP_PROCESSOR;
  10.585 +	/* Either an integrated APIC or a discrete 82489DX. */
  10.586 +	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
  10.587 +	processor.mpc_cpuflag = CPU_ENABLED;
  10.588 +	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
  10.589 +				   (boot_cpu_data.x86_model << 4) |
  10.590 +				   boot_cpu_data.x86_mask;
  10.591 +	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
  10.592 +	processor.mpc_reserved[0] = 0;
  10.593 +	processor.mpc_reserved[1] = 0;
  10.594 +	for (i = 0; i < 2; i++) {
  10.595 +		processor.mpc_apicid = i;
  10.596 +		MP_processor_info(&processor);
  10.597 +	}
  10.598 +
  10.599 +	bus.mpc_type = MP_BUS;
  10.600 +	bus.mpc_busid = 0;
  10.601 +	switch (mpc_default_type) {
  10.602 +		default:
  10.603 +			printk("???\n");
  10.604 +			printk(KERN_ERR "Unknown standard configuration %d\n",
  10.605 +				mpc_default_type);
  10.606 +			/* fall through */
  10.607 +		case 1:
  10.608 +		case 5:
  10.609 +			memcpy(bus.mpc_bustype, "ISA   ", 6);
  10.610 +			break;
  10.611 +		case 2:
  10.612 +		case 6:
  10.613 +		case 3:
  10.614 +			memcpy(bus.mpc_bustype, "EISA  ", 6);
  10.615 +			break;
  10.616 +		case 4:
  10.617 +		case 7:
  10.618 +			memcpy(bus.mpc_bustype, "MCA   ", 6);
  10.619 +	}
  10.620 +	MP_bus_info(&bus);
  10.621 +	if (mpc_default_type > 4) {
  10.622 +		bus.mpc_busid = 1;
  10.623 +		memcpy(bus.mpc_bustype, "PCI   ", 6);
  10.624 +		MP_bus_info(&bus);
  10.625 +	}
  10.626 +
  10.627 +	ioapic.mpc_type = MP_IOAPIC;
  10.628 +	ioapic.mpc_apicid = 2;
  10.629 +	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
  10.630 +	ioapic.mpc_flags = MPC_APIC_USABLE;
  10.631 +	ioapic.mpc_apicaddr = 0xFEC00000;
  10.632 +	MP_ioapic_info(&ioapic);
  10.633 +
  10.634 +	/*
  10.635 +	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
  10.636 +	 */
  10.637 +	construct_default_ioirq_mptable(mpc_default_type);
  10.638 +
  10.639 +	lintsrc.mpc_type = MP_LINTSRC;
  10.640 +	lintsrc.mpc_irqflag = 0;		/* conforming */
  10.641 +	lintsrc.mpc_srcbusid = 0;
  10.642 +	lintsrc.mpc_srcbusirq = 0;
  10.643 +	lintsrc.mpc_destapic = MP_APIC_ALL;
  10.644 +	for (i = 0; i < 2; i++) {
  10.645 +		lintsrc.mpc_irqtype = linttypes[i];
  10.646 +		lintsrc.mpc_destapiclint = i;
  10.647 +		MP_lintsrc_info(&lintsrc);
  10.648 +	}
  10.649 +}
  10.650 +
  10.651 +static struct intel_mp_floating *mpf_found;
  10.652 +
  10.653 +/*
  10.654 + * Scan the memory blocks for an SMP configuration block.
  10.655 + */
  10.656 +void __init get_smp_config (void)
  10.657 +{
  10.658 +	struct intel_mp_floating *mpf = mpf_found;
  10.659 +
  10.660 +	/*
  10.661 +	 * ACPI may be used to obtain the entire SMP configuration or just to 
  10.662 +	 * enumerate/configure processors (CONFIG_ACPI_BOOT).  Note that 
  10.663 +	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
  10.664 +	 * processors, where MPS only supports physical.
  10.665 +	 */
  10.666 +	if (acpi_lapic && acpi_ioapic) {
  10.667 +		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
  10.668 +		return;
  10.669 +	}
  10.670 +	else if (acpi_lapic)
  10.671 +		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
  10.672 +
  10.673 +	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
  10.674 +	if (mpf->mpf_feature2 & (1<<7)) {
  10.675 +		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
  10.676 +		pic_mode = 1;
  10.677 +	} else {
  10.678 +		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
  10.679 +		pic_mode = 0;
  10.680 +	}
  10.681 +
  10.682 +	/*
  10.683 +	 * Now see if we need to read further.
  10.684 +	 */
  10.685 +	if (mpf->mpf_feature1 != 0) {
  10.686 +
  10.687 +		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
  10.688 +		construct_default_ISA_mptable(mpf->mpf_feature1);
  10.689 +
  10.690 +	} else if (mpf->mpf_physptr) {
  10.691 +
  10.692 +		/*
  10.693 +		 * Read the physical hardware table.  Anything here will
  10.694 +		 * override the defaults.
  10.695 +		 */
  10.696 +		if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
  10.697 +			smp_found_config = 0;
  10.698 +			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
  10.699 +			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
  10.700 +			return;
  10.701 +		}
  10.702 +		/*
  10.703 +		 * If there are no explicit MP IRQ entries, then we are
  10.704 +		 * broken.  We set up most of the low 16 IO-APIC pins to
  10.705 +		 * ISA defaults and hope it will work.
  10.706 +		 */
  10.707 +		if (!mp_irq_entries) {
  10.708 +			struct mpc_config_bus bus;
  10.709 +
  10.710 +			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
  10.711 +
  10.712 +			bus.mpc_type = MP_BUS;
  10.713 +			bus.mpc_busid = 0;
  10.714 +			memcpy(bus.mpc_bustype, "ISA   ", 6);
  10.715 +			MP_bus_info(&bus);
  10.716 +
  10.717 +			construct_default_ioirq_mptable(0);
  10.718 +		}
  10.719 +
  10.720 +	} else
  10.721 +		BUG();
  10.722 +
  10.723 +	printk(KERN_INFO "Processors: %d\n", num_processors);
  10.724 +	/*
  10.725 +	 * Only use the first configuration found.
  10.726 +	 */
  10.727 +}
  10.728 +
  10.729 +static int __init smp_scan_config (unsigned long base, unsigned long length)
  10.730 +{
  10.731 +	unsigned long *bp = isa_bus_to_virt(base);
  10.732 +	struct intel_mp_floating *mpf;
  10.733 +
  10.734 +	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
  10.735 +	if (sizeof(*mpf) != 16)
  10.736 +		printk("Error: MPF size\n");
  10.737 +
  10.738 +	while (length > 0) {
  10.739 +		mpf = (struct intel_mp_floating *)bp;
  10.740 +		if ((*bp == SMP_MAGIC_IDENT) &&
  10.741 +			(mpf->mpf_length == 1) &&
  10.742 +			!mpf_checksum((unsigned char *)bp, 16) &&
  10.743 +			((mpf->mpf_specification == 1)
  10.744 +				|| (mpf->mpf_specification == 4)) ) {
  10.745 +
  10.746 +			smp_found_config = 1;
  10.747 +			printk(KERN_INFO "found SMP MP-table at %08lx\n",
  10.748 +						virt_to_phys(mpf));
  10.749 +			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
  10.750 +			if (mpf->mpf_physptr) {
  10.751 +				/*
  10.752 +				 * We cannot access to MPC table to compute
  10.753 +				 * table size yet, as only few megabytes from
  10.754 +				 * the bottom is mapped now.
  10.755 +				 * PC-9800's MPC table places on the very last
  10.756 +				 * of physical memory; so that simply reserving
  10.757 +				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
  10.758 +				 * in reserve_bootmem.
  10.759 +				 */
  10.760 +				unsigned long size = PAGE_SIZE;
  10.761 +				unsigned long end = max_low_pfn * PAGE_SIZE;
  10.762 +				if (mpf->mpf_physptr + size > end)
  10.763 +					size = end - mpf->mpf_physptr;
  10.764 +				reserve_bootmem(mpf->mpf_physptr, size);
  10.765 +			}
  10.766 +
  10.767 +			mpf_found = mpf;
  10.768 +			return 1;
  10.769 +		}
  10.770 +		bp += 4;
  10.771 +		length -= 16;
  10.772 +	}
  10.773 +	return 0;
  10.774 +}
  10.775 +
  10.776 +void __init find_smp_config (void)
  10.777 +{
  10.778 +	unsigned int address;
  10.779 +
  10.780 +	/*
  10.781 +	 * FIXME: Linux assumes you have 640K of base ram..
  10.782 +	 * this continues the error...
  10.783 +	 *
  10.784 +	 * 1) Scan the bottom 1K for a signature
  10.785 +	 * 2) Scan the top 1K of base RAM
  10.786 +	 * 3) Scan the 64K of bios
  10.787 +	 */
  10.788 +	if (smp_scan_config(0x0,0x400) ||
  10.789 +		smp_scan_config(639*0x400,0x400) ||
  10.790 +			smp_scan_config(0xF0000,0x10000))
  10.791 +		return;
  10.792 +	/*
  10.793 +	 * If it is an SMP machine we should know now, unless the
  10.794 +	 * configuration is in an EISA/MCA bus machine with an
  10.795 +	 * extended bios data area.
  10.796 +	 *
  10.797 +	 * there is a real-mode segmented pointer pointing to the
  10.798 +	 * 4K EBDA area at 0x40E, calculate and scan it here.
  10.799 +	 *
  10.800 +	 * NOTE! There are Linux loaders that will corrupt the EBDA
  10.801 +	 * area, and as such this kind of SMP config may be less
  10.802 +	 * trustworthy, simply because the SMP table may have been
  10.803 +	 * stomped on during early boot. These loaders are buggy and
  10.804 +	 * should be fixed.
  10.805 +	 *
  10.806 +	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
  10.807 +	 */
  10.808 +
  10.809 +	address = get_bios_ebda();
  10.810 +	if (address)
  10.811 +		smp_scan_config(address, 0x400);
  10.812 +}
  10.813 +
  10.814 +/* --------------------------------------------------------------------------
  10.815 +                            ACPI-based MP Configuration
  10.816 +   -------------------------------------------------------------------------- */
  10.817 +
  10.818 +#ifdef CONFIG_ACPI_BOOT
  10.819 +
  10.820 +void __init mp_register_lapic_address (
  10.821 +	u64			address)
  10.822 +{
  10.823 +	mp_lapic_addr = (unsigned long) address;
  10.824 +
  10.825 +	if (boot_cpu_physical_apicid == -1U)
  10.826 +		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
  10.827 +
  10.828 +	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
  10.829 +}
  10.830 +
  10.831 +
  10.832 +void __init mp_register_lapic (
  10.833 +	u8			id, 
  10.834 +	u8			enabled)
  10.835 +{
  10.836 +	struct mpc_config_processor processor;
  10.837 +	int			boot_cpu = 0;
  10.838 +	
  10.839 +	if (MAX_APICS - id <= 0) {
  10.840 +		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
  10.841 +			id, MAX_APICS);
  10.842 +		return;
  10.843 +	}
  10.844 +
  10.845 +	if (id == boot_cpu_physical_apicid)
  10.846 +		boot_cpu = 1;
  10.847 +
  10.848 +	processor.mpc_type = MP_PROCESSOR;
  10.849 +	processor.mpc_apicid = id;
  10.850 +	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
  10.851 +	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
  10.852 +	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
  10.853 +	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
  10.854 +		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
  10.855 +	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
  10.856 +	processor.mpc_reserved[0] = 0;
  10.857 +	processor.mpc_reserved[1] = 0;
  10.858 +
  10.859 +	MP_processor_info(&processor);
  10.860 +}
  10.861 +
  10.862 +#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
  10.863 +
  10.864 +#define MP_ISA_BUS		0
  10.865 +#define MP_MAX_IOAPIC_PIN	127
  10.866 +
  10.867 +struct mp_ioapic_routing {
  10.868 +	int			apic_id;
  10.869 +	int			gsi_base;
  10.870 +	int			gsi_end;
  10.871 +	u32			pin_programmed[4];
  10.872 +} mp_ioapic_routing[MAX_IO_APICS];
  10.873 +
  10.874 +
  10.875 +static int mp_find_ioapic (
  10.876 +	int			gsi)
  10.877 +{
  10.878 +	int			i = 0;
  10.879 +
  10.880 +	/* Find the IOAPIC that manages this GSI. */
  10.881 +	for (i = 0; i < nr_ioapics; i++) {
  10.882 +		if ((gsi >= mp_ioapic_routing[i].gsi_base)
  10.883 +			&& (gsi <= mp_ioapic_routing[i].gsi_end))
  10.884 +			return i;
  10.885 +	}
  10.886 +
  10.887 +	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
  10.888 +
  10.889 +	return -1;
  10.890 +}
  10.891 +	
  10.892 +
  10.893 +void __init mp_register_ioapic (
  10.894 +	u8			id, 
  10.895 +	u32			address,
  10.896 +	u32			gsi_base)
  10.897 +{
  10.898 +	int			idx = 0;
  10.899 +
  10.900 +	if (nr_ioapics >= MAX_IO_APICS) {
  10.901 +		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
  10.902 +			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
  10.903 +		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
  10.904 +	}
  10.905 +	if (!address) {
  10.906 +		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
  10.907 +			" found in MADT table, skipping!\n");
  10.908 +		return;
  10.909 +	}
  10.910 +
  10.911 +	idx = nr_ioapics++;
  10.912 +
  10.913 +	mp_ioapics[idx].mpc_type = MP_IOAPIC;
  10.914 +	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
  10.915 +	mp_ioapics[idx].mpc_apicaddr = address;
  10.916 +
  10.917 +	mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
  10.918 +	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
  10.919 +	
  10.920 +	/* 
  10.921 +	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
  10.922 +	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
  10.923 +	 */
  10.924 +	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
  10.925 +	mp_ioapic_routing[idx].gsi_base = gsi_base;
  10.926 +	mp_ioapic_routing[idx].gsi_end = gsi_base + 
  10.927 +		io_apic_get_redir_entries(idx);
  10.928 +
  10.929 +	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, "
  10.930 +		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
  10.931 +		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
  10.932 +		mp_ioapic_routing[idx].gsi_base,
  10.933 +		mp_ioapic_routing[idx].gsi_end);
  10.934 +
  10.935 +	return;
  10.936 +}
  10.937 +
  10.938 +
  10.939 +void __init mp_override_legacy_irq (
  10.940 +	u8			bus_irq,
  10.941 +	u8			polarity, 
  10.942 +	u8			trigger, 
  10.943 +	u32			gsi)
  10.944 +{
  10.945 +	struct mpc_config_intsrc intsrc;
  10.946 +	int			ioapic = -1;
  10.947 +	int			pin = -1;
  10.948 +
  10.949 +	/* 
  10.950 +	 * Convert 'gsi' to 'ioapic.pin'.
  10.951 +	 */
  10.952 +	ioapic = mp_find_ioapic(gsi);
  10.953 +	if (ioapic < 0)
  10.954 +		return;
  10.955 +	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
  10.956 +
  10.957 +	/*
  10.958 +	 * TBD: This check is for faulty timer entries, where the override
  10.959 +	 *      erroneously sets the trigger to level, resulting in a HUGE 
  10.960 +	 *      increase of timer interrupts!
  10.961 +	 */
  10.962 +	if ((bus_irq == 0) && (trigger == 3))
  10.963 +		trigger = 1;
  10.964 +
  10.965 +	intsrc.mpc_type = MP_INTSRC;
  10.966 +	intsrc.mpc_irqtype = mp_INT;
  10.967 +	intsrc.mpc_irqflag = (trigger << 2) | polarity;
  10.968 +	intsrc.mpc_srcbus = MP_ISA_BUS;
  10.969 +	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
  10.970 +	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
  10.971 +	intsrc.mpc_dstirq = pin;				    /* INTIN# */
  10.972 +
  10.973 +	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
  10.974 +		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
  10.975 +		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
  10.976 +		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
  10.977 +
  10.978 +	mp_irqs[mp_irq_entries] = intsrc;
  10.979 +	if (++mp_irq_entries == MAX_IRQ_SOURCES)
  10.980 +		panic("Max # of irq sources exceeded!\n");
  10.981 +
  10.982 +	return;
  10.983 +}
  10.984 +
  10.985 +
  10.986 +void __init mp_config_acpi_legacy_irqs (void)
  10.987 +{
  10.988 +	struct mpc_config_intsrc intsrc;
  10.989 +	int			i = 0;
  10.990 +	int			ioapic = -1;
  10.991 +
  10.992 +	/* 
  10.993 +	 * Fabricate the legacy ISA bus (bus #31).
  10.994 +	 */
  10.995 +	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
  10.996 +	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
  10.997 +
  10.998 +	/*
  10.999 +	 * ES7000 has no legacy identity mappings
 10.1000 +	 */
 10.1001 +	if (es7000_plat)
 10.1002 +		return;
 10.1003 +
 10.1004 +	/* 
 10.1005 +	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
 10.1006 +	 */
 10.1007 +	ioapic = mp_find_ioapic(0);
 10.1008 +	if (ioapic < 0)
 10.1009 +		return;
 10.1010 +
 10.1011 +	intsrc.mpc_type = MP_INTSRC;
 10.1012 +	intsrc.mpc_irqflag = 0;					/* Conforming */
 10.1013 +	intsrc.mpc_srcbus = MP_ISA_BUS;
 10.1014 +	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
 10.1015 +
 10.1016 +	/* 
 10.1017 +	 * Use the default configuration for the IRQs 0-15.  Unless
 10.1018 +	 * overriden by (MADT) interrupt source override entries.
 10.1019 +	 */
 10.1020 +	for (i = 0; i < 16; i++) {
 10.1021 +		int idx;
 10.1022 +
 10.1023 +		for (idx = 0; idx < mp_irq_entries; idx++) {
 10.1024 +			struct mpc_config_intsrc *irq = mp_irqs + idx;
 10.1025 +
 10.1026 +			/* Do we already have a mapping for this ISA IRQ? */
 10.1027 +			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
 10.1028 +				break;
 10.1029 +
 10.1030 +			/* Do we already have a mapping for this IOAPIC pin */
 10.1031 +			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
 10.1032 +				(irq->mpc_dstirq == i))
 10.1033 +				break;
 10.1034 +		}
 10.1035 +
 10.1036 +		if (idx != mp_irq_entries) {
 10.1037 +			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
 10.1038 +			continue;			/* IRQ already used */
 10.1039 +		}
 10.1040 +
 10.1041 +		intsrc.mpc_irqtype = mp_INT;
 10.1042 +		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
 10.1043 +		intsrc.mpc_dstirq = i;
 10.1044 +
 10.1045 +		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
 10.1046 +			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
 10.1047 +			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
 10.1048 +			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
 10.1049 +			intsrc.mpc_dstirq);
 10.1050 +
 10.1051 +		mp_irqs[mp_irq_entries] = intsrc;
 10.1052 +		if (++mp_irq_entries == MAX_IRQ_SOURCES)
 10.1053 +			panic("Max # of irq sources exceeded!\n");
 10.1054 +	}
 10.1055 +}
 10.1056 +
 10.1057 +int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 10.1058 +{
 10.1059 +	int			ioapic = -1;
 10.1060 +	int			ioapic_pin = 0;
 10.1061 +	int			idx, bit = 0;
 10.1062 +
 10.1063 +#ifdef CONFIG_ACPI_BUS
 10.1064 +	/* Don't set up the ACPI SCI because it's already set up */
 10.1065 +	if (acpi_fadt.sci_int == gsi)
 10.1066 +		return gsi;
 10.1067 +#endif
 10.1068 +
 10.1069 +	ioapic = mp_find_ioapic(gsi);
 10.1070 +	if (ioapic < 0) {
 10.1071 +		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
 10.1072 +		return gsi;
 10.1073 +	}
 10.1074 +
 10.1075 +	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
 10.1076 +
 10.1077 +	if (ioapic_renumber_irq)
 10.1078 +		gsi = ioapic_renumber_irq(ioapic, gsi);
 10.1079 +
 10.1080 +	/* 
 10.1081 +	 * Avoid pin reprogramming.  PRTs typically include entries  
 10.1082 +	 * with redundant pin->gsi mappings (but unique PCI devices);
 10.1083 +	 * we only program the IOAPIC on the first.
 10.1084 +	 */
 10.1085 +	bit = ioapic_pin % 32;
 10.1086 +	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
 10.1087 +	if (idx > 3) {
 10.1088 +		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 10.1089 +			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
 10.1090 +			ioapic_pin);
 10.1091 +		return gsi;
 10.1092 +	}
 10.1093 +	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
 10.1094 +		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 10.1095 +			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 10.1096 +		return gsi;
 10.1097 +	}
 10.1098 +
 10.1099 +	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 10.1100 +
 10.1101 +	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
 10.1102 +		    edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
 10.1103 +		    active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
 10.1104 +	return gsi;
 10.1105 +}
 10.1106 +
 10.1107 +#endif /*CONFIG_X86_IO_APIC && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)*/
 10.1108 +#endif /*CONFIG_ACPI_BOOT*/
    11.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/pci/Makefile	Tue May 03 12:28:27 2005 +0000
    11.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/pci/Makefile	Tue May 03 14:27:54 2005 +0000
    11.3 @@ -6,12 +6,12 @@ c-obj-y				:= i386.o
    11.4  
    11.5  c-obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
    11.6  c-obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o
    11.7 -obj-$(CONFIG_PCI_DIRECT)	+= direct.o
    11.8 +c-obj-$(CONFIG_PCI_DIRECT)	+= direct.o
    11.9  
   11.10  c-pci-y				:= fixup.o
   11.11  c-pci-$(CONFIG_ACPI_PCI)	+= acpi.o
   11.12  c-pci-y				+= legacy.o
   11.13 -pci-y				+= irq.o
   11.14 +c-pci-y				+= irq.o
   11.15  
   11.16  c-pci-$(CONFIG_X86_VISWS)	:= visws.o fixup.o
   11.17  pci-$(CONFIG_X86_VISWS)		:=
    12.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/pci/direct.c	Tue May 03 12:28:27 2005 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,81 +0,0 @@
    12.4 -/*
    12.5 - * direct.c - Low-level direct PCI config space access
    12.6 - */
    12.7 -
    12.8 -#include <linux/pci.h>
    12.9 -#include <linux/init.h>
   12.10 -#include "pci.h"
   12.11 -
   12.12 -#include <asm-xen/xen-public/xen.h>
   12.13 -#include <asm-xen/xen-public/physdev.h>
   12.14 -
   12.15 -/*
   12.16 - * Functions for accessing PCI configuration space with type xen accesses
   12.17 - */
   12.18 -
   12.19 -static int pci_conf_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
   12.20 -{
   12.21 -	unsigned long flags;
   12.22 -	physdev_op_t op;
   12.23 -	int ret;
   12.24 -
   12.25 -	if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
   12.26 -		return -EINVAL;
   12.27 -
   12.28 -	spin_lock_irqsave(&pci_config_lock, flags);
   12.29 -
   12.30 -	op.cmd = PHYSDEVOP_PCI_CFGREG_READ;
   12.31 -	op.u.pci_cfgreg_read.bus  = bus;
   12.32 -	op.u.pci_cfgreg_read.dev  = (devfn & ~0x7) >> 3;
   12.33 -	op.u.pci_cfgreg_read.func = devfn & 0x7;
   12.34 -	op.u.pci_cfgreg_read.reg  = reg;
   12.35 -	op.u.pci_cfgreg_read.len  = len;
   12.36 -
   12.37 -	ret = HYPERVISOR_physdev_op(&op);
   12.38 -	if (ret == 0)
   12.39 -		*value = op.u.pci_cfgreg_read.value;
   12.40 -
   12.41 -	spin_unlock_irqrestore(&pci_config_lock, flags);
   12.42 -
   12.43 -	return ret;
   12.44 -}
   12.45 -
   12.46 -static int pci_conf_write (int seg, int bus, int devfn, int reg, int len, u32 value)
   12.47 -{
   12.48 -	unsigned long flags;
   12.49 -	physdev_op_t op;
   12.50 -	int ret;
   12.51 -
   12.52 -	if ((bus > 255) || (devfn > 255) || (reg > 255)) 
   12.53 -		return -EINVAL;
   12.54 -
   12.55 -	spin_lock_irqsave(&pci_config_lock, flags);
   12.56 -
   12.57 -	op.cmd = PHYSDEVOP_PCI_CFGREG_WRITE;
   12.58 -	op.u.pci_cfgreg_write.bus   = bus;
   12.59 -	op.u.pci_cfgreg_write.dev   = (devfn & ~0x7) >> 3;
   12.60 -	op.u.pci_cfgreg_write.func  = devfn & 0x7;
   12.61 -	op.u.pci_cfgreg_write.reg   = reg;
   12.62 -	op.u.pci_cfgreg_write.len   = len;
   12.63 -	op.u.pci_cfgreg_write.value = value;
   12.64 -
   12.65 -	ret = HYPERVISOR_physdev_op(&op);
   12.66 -
   12.67 -	spin_unlock_irqrestore(&pci_config_lock, flags);
   12.68 -
   12.69 -	return ret;
   12.70 -}
   12.71 -
   12.72 -struct pci_raw_ops pci_direct_xen = {
   12.73 -	.read =		pci_conf_read,
   12.74 -	.write =	pci_conf_write,
   12.75 -};
   12.76 -
   12.77 -static int __init pci_direct_init(void)
   12.78 -{
   12.79 -	printk(KERN_INFO "PCI: Using configuration type Xen\n");
   12.80 -	raw_pci_ops = &pci_direct_xen;
   12.81 -	return 0;
   12.82 -}
   12.83 -
   12.84 -arch_initcall(pci_direct_init);
    13.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/pci/irq.c	Tue May 03 12:28:27 2005 +0000
    13.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/pci/irq.c	Tue May 03 14:27:54 2005 +0000
    13.3 @@ -12,6 +12,7 @@
    13.4  #include <linux/slab.h>
    13.5  #include <linux/interrupt.h>
    13.6  #include <linux/irq.h>
    13.7 +#include <linux/dmi.h>
    13.8  #include <asm/io.h>
    13.9  #include <asm/smp.h>
   13.10  #include <asm/io_apic.h>
   13.11 @@ -20,8 +21,15 @@
   13.12  
   13.13  #include "pci.h"
   13.14  
   13.15 -#include <asm-xen/xen-public/xen.h>
   13.16 -#include <asm-xen/xen-public/physdev.h>
   13.17 +#define DBG printk
   13.18 +
   13.19 +#define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
   13.20 +#define PIRQ_VERSION 0x0100
   13.21 +
   13.22 +static int broken_hp_bios_irq9;
   13.23 +static int acer_tm360_irqrouting;
   13.24 +
   13.25 +static struct irq_routing_table *pirq_table;
   13.26  
   13.27  static int pirq_enable_irq(struct pci_dev *dev);
   13.28  
   13.29 @@ -37,33 +45,963 @@ static int pirq_penalty[16] = {
   13.30  	0, 0, 0, 0, 1000, 100000, 100000, 100000
   13.31  };
   13.32  
   13.33 +struct irq_router {
   13.34 +	char *name;
   13.35 +	u16 vendor, device;
   13.36 +	int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
   13.37 +	int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
   13.38 +};
   13.39 +
   13.40 +struct irq_router_handler {
   13.41 +	u16 vendor;
   13.42 +	int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
   13.43 +};
   13.44 +
   13.45  int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
   13.46  
   13.47 +/*
   13.48 + *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
   13.49 + */
   13.50 +
   13.51 +static struct irq_routing_table * __init pirq_find_routing_table(void)
   13.52 +{
   13.53 +	u8 *addr;
   13.54 +	struct irq_routing_table *rt;
   13.55 +	int i;
   13.56 +	u8 sum;
   13.57 +
   13.58 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
   13.59 +	for(addr = (u8 *) isa_bus_to_virt(0xf0000); addr < (u8 *) isa_bus_to_virt(0x100000); addr += 16) {
   13.60 +		rt = (struct irq_routing_table *) addr;
   13.61 +		if (rt->signature != PIRQ_SIGNATURE ||
   13.62 +		    rt->version != PIRQ_VERSION ||
   13.63 +		    rt->size % 16 ||
   13.64 +		    rt->size < sizeof(struct irq_routing_table))
   13.65 +			continue;
   13.66 +		sum = 0;
   13.67 +		for(i=0; i<rt->size; i++)
   13.68 +			sum += addr[i];
   13.69 +		if (!sum) {
   13.70 +			DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
   13.71 +			return rt;
   13.72 +		}
   13.73 +	}
   13.74 +#endif
   13.75 +	
   13.76 +	return NULL;
   13.77 +}
   13.78 +
   13.79 +/*
   13.80 + *  If we have a IRQ routing table, use it to search for peer host
   13.81 + *  bridges.  It's a gross hack, but since there are no other known
   13.82 + *  ways how to get a list of buses, we have to go this way.
   13.83 + */
   13.84 +
   13.85 +static void __init pirq_peer_trick(void)
   13.86 +{
   13.87 +	struct irq_routing_table *rt = pirq_table;
   13.88 +	u8 busmap[256];
   13.89 +	int i;
   13.90 +	struct irq_info *e;
   13.91 +
   13.92 +	memset(busmap, 0, sizeof(busmap));
   13.93 +	for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
   13.94 +		e = &rt->slots[i];
   13.95 +#ifdef DEBUG
   13.96 +		{
   13.97 +			int j;
   13.98 +			DBG("%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
   13.99 +			for(j=0; j<4; j++)
  13.100 +				DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
  13.101 +			DBG("\n");
  13.102 +		}
  13.103 +#endif
  13.104 +		busmap[e->bus] = 1;
  13.105 +	}
  13.106 +	for(i = 1; i < 256; i++) {
  13.107 +		if (!busmap[i] || pci_find_bus(0, i))
  13.108 +			continue;
  13.109 +		if (pci_scan_bus(i, &pci_root_ops, NULL))
  13.110 +			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
  13.111 +	}
  13.112 +	pcibios_last_bus = -1;
  13.113 +}
  13.114 +
  13.115 +/*
  13.116 + *  Code for querying and setting of IRQ routes on various interrupt routers.
  13.117 + */
  13.118 +
  13.119 +void eisa_set_level_irq(unsigned int irq)
  13.120 +{
  13.121 +	unsigned char mask = 1 << (irq & 7);
  13.122 +	unsigned int port = 0x4d0 + (irq >> 3);
  13.123 +	unsigned char val;
  13.124 +	static u16 eisa_irq_mask;
  13.125 +
  13.126 +	if (irq >= 16 || (1 << irq) & eisa_irq_mask)
  13.127 +		return;
  13.128 +
  13.129 +	eisa_irq_mask |= (1 << irq);
  13.130 +	printk("PCI: setting IRQ %u as level-triggered\n", irq);
  13.131 +	val = inb(port);
  13.132 +	if (!(val & mask)) {
  13.133 +		DBG(" -> edge");
  13.134 +		outb(val | mask, port);
  13.135 +	}
  13.136 +}
  13.137 +
  13.138 +/*
  13.139 + * Common IRQ routing practice: nybbles in config space,
  13.140 + * offset by some magic constant.
  13.141 + */
  13.142 +static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
  13.143 +{
  13.144 +	u8 x;
  13.145 +	unsigned reg = offset + (nr >> 1);
  13.146 +
  13.147 +	pci_read_config_byte(router, reg, &x);
  13.148 +	return (nr & 1) ? (x >> 4) : (x & 0xf);
  13.149 +}
  13.150 +
  13.151 +static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
  13.152 +{
  13.153 +	u8 x;
  13.154 +	unsigned reg = offset + (nr >> 1);
  13.155 +
  13.156 +	pci_read_config_byte(router, reg, &x);
  13.157 +	x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
  13.158 +	pci_write_config_byte(router, reg, x);
  13.159 +}
  13.160 +
  13.161 +/*
  13.162 + * ALI pirq entries are damn ugly, and completely undocumented.
  13.163 + * This has been figured out from pirq tables, and it's not a pretty
  13.164 + * picture.
  13.165 + */
  13.166 +static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.167 +{
  13.168 +	static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
  13.169 +
  13.170 +	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
  13.171 +}
  13.172 +
  13.173 +static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.174 +{
  13.175 +	static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
  13.176 +	unsigned int val = irqmap[irq];
  13.177 +		
  13.178 +	if (val) {
  13.179 +		write_config_nybble(router, 0x48, pirq-1, val);
  13.180 +		return 1;
  13.181 +	}
  13.182 +	return 0;
  13.183 +}
  13.184 +
  13.185 +/*
  13.186 + * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
  13.187 + * just a pointer to the config space.
  13.188 + */
  13.189 +static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.190 +{
  13.191 +	u8 x;
  13.192 +
  13.193 +	pci_read_config_byte(router, pirq, &x);
  13.194 +	return (x < 16) ? x : 0;
  13.195 +}
  13.196 +
  13.197 +static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.198 +{
  13.199 +	pci_write_config_byte(router, pirq, irq);
  13.200 +	return 1;
  13.201 +}
  13.202 +
  13.203 +/*
  13.204 + * The VIA pirq rules are nibble-based, like ALI,
  13.205 + * but without the ugly irq number munging.
  13.206 + * However, PIRQD is in the upper instead of lower 4 bits.
  13.207 + */
  13.208 +static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.209 +{
  13.210 +	return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
  13.211 +}
  13.212 +
  13.213 +static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.214 +{
  13.215 +	write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
  13.216 +	return 1;
  13.217 +}
  13.218 +
  13.219 +/*
  13.220 + * ITE 8330G pirq rules are nibble-based
  13.221 + * FIXME: pirqmap may be { 1, 0, 3, 2 },
  13.222 + * 	  2+3 are both mapped to irq 9 on my system
  13.223 + */
  13.224 +static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.225 +{
  13.226 +	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
  13.227 +	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
  13.228 +}
  13.229 +
  13.230 +static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.231 +{
  13.232 +	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
  13.233 +	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
  13.234 +	return 1;
  13.235 +}
  13.236 +
  13.237 +/*
  13.238 + * OPTI: high four bits are nibble pointer..
  13.239 + * I wonder what the low bits do?
  13.240 + */
  13.241 +static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.242 +{
  13.243 +	return read_config_nybble(router, 0xb8, pirq >> 4);
  13.244 +}
  13.245 +
  13.246 +static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.247 +{
  13.248 +	write_config_nybble(router, 0xb8, pirq >> 4, irq);
  13.249 +	return 1;
  13.250 +}
  13.251 +
  13.252 +/*
  13.253 + * Cyrix: nibble offset 0x5C
  13.254 + * 0x5C bits 7:4 is INTB bits 3:0 is INTA 
  13.255 + * 0x5D bits 7:4 is INTD bits 3:0 is INTC
  13.256 + */
  13.257 +static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.258 +{
  13.259 +	return read_config_nybble(router, 0x5C, (pirq-1)^1);
  13.260 +}
  13.261 +
  13.262 +static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.263 +{
  13.264 +	write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
  13.265 +	return 1;
  13.266 +}
  13.267 +
  13.268 +/*
  13.269 + *	PIRQ routing for SiS 85C503 router used in several SiS chipsets.
  13.270 + *	We have to deal with the following issues here:
  13.271 + *	- vendors have different ideas about the meaning of link values
  13.272 + *	- some onboard devices (integrated in the chipset) have special
  13.273 + *	  links and are thus routed differently (i.e. not via PCI INTA-INTD)
  13.274 + *	- different revision of the router have a different layout for
  13.275 + *	  the routing registers, particularly for the onchip devices
  13.276 + *
  13.277 + *	For all routing registers the common thing is we have one byte
  13.278 + *	per routeable link which is defined as:
  13.279 + *		 bit 7      IRQ mapping enabled (0) or disabled (1)
  13.280 + *		 bits [6:4] reserved (sometimes used for onchip devices)
  13.281 + *		 bits [3:0] IRQ to map to
  13.282 + *		     allowed: 3-7, 9-12, 14-15
  13.283 + *		     reserved: 0, 1, 2, 8, 13
  13.284 + *
  13.285 + *	The config-space registers located at 0x41/0x42/0x43/0x44 are
  13.286 + *	always used to route the normal PCI INT A/B/C/D respectively.
  13.287 + *	Apparently there are systems implementing PCI routing table using
  13.288 + *	link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
  13.289 + *	We try our best to handle both link mappings.
  13.290 + *	
  13.291 + *	Currently (2003-05-21) it appears most SiS chipsets follow the
  13.292 + *	definition of routing registers from the SiS-5595 southbridge.
  13.293 + *	According to the SiS 5595 datasheets the revision id's of the
  13.294 + *	router (ISA-bridge) should be 0x01 or 0xb0.
  13.295 + *
  13.296 + *	Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
  13.297 + *	Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
  13.298 + *	They seem to work with the current routing code. However there is
  13.299 + *	some concern because of the two USB-OHCI HCs (original SiS 5595
  13.300 + *	had only one). YMMV.
  13.301 + *
  13.302 + *	Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
  13.303 + *
  13.304 + *	0x61:	IDEIRQ:
  13.305 + *		bits [6:5] must be written 01
  13.306 + *		bit 4 channel-select primary (0), secondary (1)
  13.307 + *
  13.308 + *	0x62:	USBIRQ:
  13.309 + *		bit 6 OHCI function disabled (0), enabled (1)
  13.310 + *	
  13.311 + *	0x6a:	ACPI/SCI IRQ: bits 4-6 reserved
  13.312 + *
  13.313 + *	0x7e:	Data Acq. Module IRQ - bits 4-6 reserved
  13.314 + *
  13.315 + *	We support USBIRQ (in addition to INTA-INTD) and keep the
  13.316 + *	IDE, ACPI and DAQ routing untouched as set by the BIOS.
  13.317 + *
  13.318 + *	Currently the only reported exception is the new SiS 65x chipset
  13.319 + *	which includes the SiS 69x southbridge. Here we have the 85C503
  13.320 + *	router revision 0x04 and there are changes in the register layout
  13.321 + *	mostly related to the different USB HCs with USB 2.0 support.
  13.322 + *
  13.323 + *	Onchip routing for router rev-id 0x04 (try-and-error observation)
  13.324 + *
  13.325 + *	0x60/0x61/0x62/0x63:	1xEHCI and 3xOHCI (companion) USB-HCs
  13.326 + *				bit 6-4 are probably unused, not like 5595
  13.327 + */
  13.328 +
  13.329 +#define PIRQ_SIS_IRQ_MASK	0x0f
  13.330 +#define PIRQ_SIS_IRQ_DISABLE	0x80
  13.331 +#define PIRQ_SIS_USB_ENABLE	0x40
  13.332 +
  13.333 +static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.334 +{
  13.335 +	u8 x;
  13.336 +	int reg;
  13.337 +
  13.338 +	reg = pirq;
  13.339 +	if (reg >= 0x01 && reg <= 0x04)
  13.340 +		reg += 0x40;
  13.341 +	pci_read_config_byte(router, reg, &x);
  13.342 +	return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
  13.343 +}
  13.344 +
  13.345 +static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.346 +{
  13.347 +	u8 x;
  13.348 +	int reg;
  13.349 +
  13.350 +	reg = pirq;
  13.351 +	if (reg >= 0x01 && reg <= 0x04)
  13.352 +		reg += 0x40;
  13.353 +	pci_read_config_byte(router, reg, &x);
  13.354 +	x &= ~(PIRQ_SIS_IRQ_MASK | PIRQ_SIS_IRQ_DISABLE);
  13.355 +	x |= irq ? irq: PIRQ_SIS_IRQ_DISABLE;
  13.356 +	pci_write_config_byte(router, reg, x);
  13.357 +	return 1;
  13.358 +}
  13.359 +
  13.360 +
  13.361 +/*
  13.362 + * VLSI: nibble offset 0x74 - educated guess due to routing table and
  13.363 + *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
  13.364 + *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
  13.365 + *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
  13.366 + *       for the busbridge to the docking station.
  13.367 + */
  13.368 +
  13.369 +static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.370 +{
  13.371 +	if (pirq > 8) {
  13.372 +		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
  13.373 +		return 0;
  13.374 +	}
  13.375 +	return read_config_nybble(router, 0x74, pirq-1);
  13.376 +}
  13.377 +
  13.378 +static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.379 +{
  13.380 +	if (pirq > 8) {
  13.381 +		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
  13.382 +		return 0;
  13.383 +	}
  13.384 +	write_config_nybble(router, 0x74, pirq-1, irq);
  13.385 +	return 1;
  13.386 +}
  13.387 +
  13.388 +/*
  13.389 + * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
  13.390 + * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
  13.391 + * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
  13.392 + * register is a straight binary coding of desired PIC IRQ (low nibble).
  13.393 + *
  13.394 + * The 'link' value in the PIRQ table is already in the correct format
  13.395 + * for the Index register.  There are some special index values:
  13.396 + * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
  13.397 + * and 0x03 for SMBus.
  13.398 + */
  13.399 +static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.400 +{
  13.401 +	outb_p(pirq, 0xc00);
  13.402 +	return inb(0xc01) & 0xf;
  13.403 +}
  13.404 +
  13.405 +static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.406 +{
  13.407 +	outb_p(pirq, 0xc00);
  13.408 +	outb_p(irq, 0xc01);
  13.409 +	return 1;
  13.410 +}
  13.411 +
  13.412 +/* Support for AMD756 PCI IRQ Routing
  13.413 + * Jhon H. Caicedo <jhcaiced@osso.org.co>
  13.414 + * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
  13.415 + * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
  13.416 + * The AMD756 pirq rules are nibble-based
  13.417 + * offset 0x56 0-3 PIRQA  4-7  PIRQB
  13.418 + * offset 0x57 0-3 PIRQC  4-7  PIRQD
  13.419 + */
  13.420 +static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
  13.421 +{
  13.422 +	u8 irq;
  13.423 +	irq = 0;
  13.424 +	if (pirq <= 4)
  13.425 +	{
  13.426 +		irq = read_config_nybble(router, 0x56, pirq - 1);
  13.427 +	}
  13.428 +	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
  13.429 +		dev->vendor, dev->device, pirq, irq);
  13.430 +	return irq;
  13.431 +}
  13.432 +
  13.433 +static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.434 +{
  13.435 +	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
  13.436 +		dev->vendor, dev->device, pirq, irq);
  13.437 +	if (pirq <= 4)
  13.438 +	{
  13.439 +		write_config_nybble(router, 0x56, pirq - 1, irq);
  13.440 +	}
  13.441 +	return 1;
  13.442 +}
  13.443 +
  13.444 +#ifdef CONFIG_PCI_BIOS
  13.445 +
  13.446 +static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
  13.447 +{
  13.448 +	struct pci_dev *bridge;
  13.449 +	int pin = pci_get_interrupt_pin(dev, &bridge);
  13.450 +	return pcibios_set_irq_routing(bridge, pin, irq);
  13.451 +}
  13.452 +
  13.453 +#endif
  13.454 +
  13.455 +static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.456 +{
  13.457 +	static struct pci_device_id pirq_440gx[] = {
  13.458 +		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
  13.459 +		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
  13.460 +		{ },
  13.461 +	};
  13.462 +
  13.463 +	/* 440GX has a proprietary PIRQ router -- don't use it */
  13.464 +	if (pci_dev_present(pirq_440gx))
  13.465 +		return 0;
  13.466 +
  13.467 +	switch(device)
  13.468 +	{
  13.469 +		case PCI_DEVICE_ID_INTEL_82371FB_0:
  13.470 +		case PCI_DEVICE_ID_INTEL_82371SB_0:
  13.471 +		case PCI_DEVICE_ID_INTEL_82371AB_0:
  13.472 +		case PCI_DEVICE_ID_INTEL_82371MX:
  13.473 +		case PCI_DEVICE_ID_INTEL_82443MX_0:
  13.474 +		case PCI_DEVICE_ID_INTEL_82801AA_0:
  13.475 +		case PCI_DEVICE_ID_INTEL_82801AB_0:
  13.476 +		case PCI_DEVICE_ID_INTEL_82801BA_0:
  13.477 +		case PCI_DEVICE_ID_INTEL_82801BA_10:
  13.478 +		case PCI_DEVICE_ID_INTEL_82801CA_0:
  13.479 +		case PCI_DEVICE_ID_INTEL_82801CA_12:
  13.480 +		case PCI_DEVICE_ID_INTEL_82801DB_0:
  13.481 +		case PCI_DEVICE_ID_INTEL_82801E_0:
  13.482 +		case PCI_DEVICE_ID_INTEL_82801EB_0:
  13.483 +		case PCI_DEVICE_ID_INTEL_ESB_1:
  13.484 +		case PCI_DEVICE_ID_INTEL_ICH6_0:
  13.485 +		case PCI_DEVICE_ID_INTEL_ICH6_1:
  13.486 +		case PCI_DEVICE_ID_INTEL_ICH7_0:
  13.487 +		case PCI_DEVICE_ID_INTEL_ICH7_1:
  13.488 +			r->name = "PIIX/ICH";
  13.489 +			r->get = pirq_piix_get;
  13.490 +			r->set = pirq_piix_set;
  13.491 +			return 1;
  13.492 +	}
  13.493 +	return 0;
  13.494 +}
  13.495 +
  13.496 +static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.497 +{
  13.498 +	/* FIXME: We should move some of the quirk fixup stuff here */
  13.499 +	switch(device)
  13.500 +	{
  13.501 +		case PCI_DEVICE_ID_VIA_82C586_0:
  13.502 +		case PCI_DEVICE_ID_VIA_82C596:
  13.503 +		case PCI_DEVICE_ID_VIA_82C686:
  13.504 +		case PCI_DEVICE_ID_VIA_8231:
  13.505 +		/* FIXME: add new ones for 8233/5 */
  13.506 +			r->name = "VIA";
  13.507 +			r->get = pirq_via_get;
  13.508 +			r->set = pirq_via_set;
  13.509 +			return 1;
  13.510 +	}
  13.511 +	return 0;
  13.512 +}
  13.513 +
  13.514 +static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.515 +{
  13.516 +	switch(device)
  13.517 +	{
  13.518 +		case PCI_DEVICE_ID_VLSI_82C534:
  13.519 +			r->name = "VLSI 82C534";
  13.520 +			r->get = pirq_vlsi_get;
  13.521 +			r->set = pirq_vlsi_set;
  13.522 +			return 1;
  13.523 +	}
  13.524 +	return 0;
  13.525 +}
  13.526 +
  13.527 +
  13.528 +static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.529 +{
  13.530 +	switch(device)
  13.531 +	{
  13.532 +		case PCI_DEVICE_ID_SERVERWORKS_OSB4:
  13.533 +		case PCI_DEVICE_ID_SERVERWORKS_CSB5:
  13.534 +			r->name = "ServerWorks";
  13.535 +			r->get = pirq_serverworks_get;
  13.536 +			r->set = pirq_serverworks_set;
  13.537 +			return 1;
  13.538 +	}
  13.539 +	return 0;
  13.540 +}
  13.541 +
  13.542 +static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.543 +{
  13.544 +	if (device != PCI_DEVICE_ID_SI_503)
  13.545 +		return 0;
  13.546 +		
  13.547 +	r->name = "SIS";
  13.548 +	r->get = pirq_sis_get;
  13.549 +	r->set = pirq_sis_set;
  13.550 +	return 1;
  13.551 +}
  13.552 +
  13.553 +static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.554 +{
  13.555 +	switch(device)
  13.556 +	{
  13.557 +		case PCI_DEVICE_ID_CYRIX_5520:
  13.558 +			r->name = "NatSemi";
  13.559 +			r->get = pirq_cyrix_get;
  13.560 +			r->set = pirq_cyrix_set;
  13.561 +			return 1;
  13.562 +	}
  13.563 +	return 0;
  13.564 +}
  13.565 +
  13.566 +static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.567 +{
  13.568 +	switch(device)
  13.569 +	{
  13.570 +		case PCI_DEVICE_ID_OPTI_82C700:
  13.571 +			r->name = "OPTI";
  13.572 +			r->get = pirq_opti_get;
  13.573 +			r->set = pirq_opti_set;
  13.574 +			return 1;
  13.575 +	}
  13.576 +	return 0;
  13.577 +}
  13.578 +
  13.579 +static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.580 +{
  13.581 +	switch(device)
  13.582 +	{
  13.583 +		case PCI_DEVICE_ID_ITE_IT8330G_0:
  13.584 +			r->name = "ITE";
  13.585 +			r->get = pirq_ite_get;
  13.586 +			r->set = pirq_ite_set;
  13.587 +			return 1;
  13.588 +	}
  13.589 +	return 0;
  13.590 +}
  13.591 +
  13.592 +static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.593 +{
  13.594 +	switch(device)
  13.595 +	{
  13.596 +	case PCI_DEVICE_ID_AL_M1533:
  13.597 +	case PCI_DEVICE_ID_AL_M1563:
  13.598 +		printk("PCI: Using ALI IRQ Router\n");
  13.599 +			r->name = "ALI";
  13.600 +			r->get = pirq_ali_get;
  13.601 +			r->set = pirq_ali_set;
  13.602 +			return 1;
  13.603 +	}
  13.604 +	return 0;
  13.605 +}
  13.606 +
  13.607 +static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
  13.608 +{
  13.609 +	switch(device)
  13.610 +	{
  13.611 +		case PCI_DEVICE_ID_AMD_VIPER_740B:
  13.612 +			r->name = "AMD756";
  13.613 +			break;
  13.614 +		case PCI_DEVICE_ID_AMD_VIPER_7413:
  13.615 +			r->name = "AMD766";
  13.616 +			break;
  13.617 +		case PCI_DEVICE_ID_AMD_VIPER_7443:
  13.618 +			r->name = "AMD768";
  13.619 +			break;
  13.620 +		default:
  13.621 +			return 0;
  13.622 +	}
  13.623 +	r->get = pirq_amd756_get;
  13.624 +	r->set = pirq_amd756_set;
  13.625 +	return 1;
  13.626 +}
  13.627 +		
  13.628 +static __initdata struct irq_router_handler pirq_routers[] = {
  13.629 +	{ PCI_VENDOR_ID_INTEL, intel_router_probe },
  13.630 +	{ PCI_VENDOR_ID_AL, ali_router_probe },
  13.631 +	{ PCI_VENDOR_ID_ITE, ite_router_probe },
  13.632 +	{ PCI_VENDOR_ID_VIA, via_router_probe },
  13.633 +	{ PCI_VENDOR_ID_OPTI, opti_router_probe },
  13.634 +	{ PCI_VENDOR_ID_SI, sis_router_probe },
  13.635 +	{ PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
  13.636 +	{ PCI_VENDOR_ID_VLSI, vlsi_router_probe },
  13.637 +	{ PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
  13.638 +	{ PCI_VENDOR_ID_AMD, amd_router_probe },
  13.639 +	/* Someone with docs needs to add the ATI Radeon IGP */
  13.640 +	{ 0, NULL }
  13.641 +};
  13.642 +static struct irq_router pirq_router;
  13.643 +static struct pci_dev *pirq_router_dev;
  13.644 +
  13.645 +
  13.646 +/*
  13.647 + *	FIXME: should we have an option to say "generic for
  13.648 + *	chipset" ?
  13.649 + */
  13.650 + 
  13.651 +static void __init pirq_find_router(struct irq_router *r)
  13.652 +{
  13.653 +	struct irq_routing_table *rt = pirq_table;
  13.654 +	struct irq_router_handler *h;
  13.655 +
  13.656 +#ifdef CONFIG_PCI_BIOS
  13.657 +	if (!rt->signature) {
  13.658 +		printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
  13.659 +		r->set = pirq_bios_set;
  13.660 +		r->name = "BIOS";
  13.661 +		return;
  13.662 +	}
  13.663 +#endif
  13.664 +
  13.665 +	/* Default unless a driver reloads it */
  13.666 +	r->name = "default";
  13.667 +	r->get = NULL;
  13.668 +	r->set = NULL;
  13.669 +	
  13.670 +	DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
  13.671 +	    rt->rtr_vendor, rt->rtr_device);
  13.672 +
  13.673 +	pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
  13.674 +	if (!pirq_router_dev) {
  13.675 +		DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
  13.676 +		return;
  13.677 +	}
  13.678 +
  13.679 +	for( h = pirq_routers; h->vendor; h++) {
  13.680 +		/* First look for a router match */
  13.681 +		if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
  13.682 +			break;
  13.683 +		/* Fall back to a device match */
  13.684 +		if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
  13.685 +			break;
  13.686 +	}
  13.687 +	printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
  13.688 +		pirq_router.name,
  13.689 +		pirq_router_dev->vendor,
  13.690 +		pirq_router_dev->device,
  13.691 +		pci_name(pirq_router_dev));
  13.692 +}
  13.693 +
  13.694 +static struct irq_info *pirq_get_info(struct pci_dev *dev)
  13.695 +{
  13.696 +	struct irq_routing_table *rt = pirq_table;
  13.697 +	int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
  13.698 +	struct irq_info *info;
  13.699 +
  13.700 +	for (info = rt->slots; entries--; info++)
  13.701 +		if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
  13.702 +			return info;
  13.703 +	return NULL;
  13.704 +}
  13.705 +
  13.706 +static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
  13.707 +{
  13.708 +	u8 pin;
  13.709 +	struct irq_info *info;
  13.710 +	int i, pirq, newirq;
  13.711 +	int irq = 0;
  13.712 +	u32 mask;
  13.713 +	struct irq_router *r = &pirq_router;
  13.714 +	struct pci_dev *dev2 = NULL;
  13.715 +	char *msg = NULL;
  13.716 +
  13.717 +	/* Find IRQ pin */
  13.718 +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
  13.719 +	if (!pin) {
  13.720 +		DBG(" -> no interrupt pin\n");
  13.721 +		return 0;
  13.722 +	}
  13.723 +	pin = pin - 1;
  13.724 +
  13.725 +	/* Find IRQ routing entry */
  13.726 +
  13.727 +	if (!pirq_table)
  13.728 +		return 0;
  13.729 +	
  13.730 +	DBG("IRQ for %s[%c]", pci_name(dev), 'A' + pin);
  13.731 +	info = pirq_get_info(dev);
  13.732 +	if (!info) {
  13.733 +		DBG(" -> not found in routing table\n");
  13.734 +		return 0;
  13.735 +	}
  13.736 +	pirq = info->irq[pin].link;
  13.737 +	mask = info->irq[pin].bitmap;
  13.738 +	if (!pirq) {
  13.739 +		DBG(" -> not routed\n");
  13.740 +		return 0;
  13.741 +	}
  13.742 +	DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
  13.743 +	mask &= pcibios_irq_mask;
  13.744 +
  13.745 +	/* Work around broken HP Pavilion Notebooks which assign USB to
  13.746 +	   IRQ 9 even though it is actually wired to IRQ 11 */
  13.747 +
  13.748 +	if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
  13.749 +		dev->irq = 11;
  13.750 +		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
  13.751 +		r->set(pirq_router_dev, dev, pirq, 11);
  13.752 +	}
  13.753 +
  13.754 +	/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
  13.755 +	if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
  13.756 +		pirq = 0x68;
  13.757 +		mask = 0x400;
  13.758 +		dev->irq = r->get(pirq_router_dev, dev, pirq);
  13.759 +		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
  13.760 +	}
  13.761 +
  13.762 +	/*
  13.763 +	 * Find the best IRQ to assign: use the one
  13.764 +	 * reported by the device if possible.
  13.765 +	 */
  13.766 +	newirq = dev->irq;
  13.767 +	if (!((1 << newirq) & mask)) {
  13.768 +		if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
  13.769 +		else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, pci_name(dev));
  13.770 +	}
  13.771 +	if (!newirq && assign) {
  13.772 +		for (i = 0; i < 16; i++) {
  13.773 +			if (!(mask & (1 << i)))
  13.774 +				continue;
  13.775 +			if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, SA_SHIRQ))
  13.776 +				newirq = i;
  13.777 +		}
  13.778 +	}
  13.779 +	DBG(" -> newirq=%d", newirq);
  13.780 +
  13.781 +	/* Check if it is hardcoded */
  13.782 +	if ((pirq & 0xf0) == 0xf0) {
  13.783 +		irq = pirq & 0xf;
  13.784 +		DBG(" -> hardcoded IRQ %d\n", irq);
  13.785 +		msg = "Hardcoded";
  13.786 +	} else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
  13.787 +	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
  13.788 +		DBG(" -> got IRQ %d\n", irq);
  13.789 +		msg = "Found";
  13.790 +	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
  13.791 +		DBG(" -> assigning IRQ %d", newirq);
  13.792 +		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
  13.793 +			eisa_set_level_irq(newirq);
  13.794 +			DBG(" ... OK\n");
  13.795 +			msg = "Assigned";
  13.796 +			irq = newirq;
  13.797 +		}
  13.798 +	}
  13.799 +
  13.800 +	if (!irq) {
  13.801 +		DBG(" ... failed\n");
  13.802 +		if (newirq && mask == (1 << newirq)) {
  13.803 +			msg = "Guessed";
  13.804 +			irq = newirq;
  13.805 +		} else
  13.806 +			return 0;
  13.807 +	}
  13.808 +	printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev));
  13.809 +
  13.810 +	/* Update IRQ for all devices with the same pirq value */
  13.811 +	while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
  13.812 +		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
  13.813 +		if (!pin)
  13.814 +			continue;
  13.815 +		pin--;
  13.816 +		info = pirq_get_info(dev2);
  13.817 +		if (!info)
  13.818 +			continue;
  13.819 +		if (info->irq[pin].link == pirq) {
  13.820 +			/* We refuse to override the dev->irq information. Give a warning! */
  13.821 +		    	if ( dev2->irq && dev2->irq != irq && \
  13.822 +			(!(pci_probe & PCI_USE_PIRQ_MASK) || \
  13.823 +			((1 << dev2->irq) & mask)) ) {
  13.824 +#ifndef CONFIG_PCI_MSI
  13.825 +		    		printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
  13.826 +				       pci_name(dev2), dev2->irq, irq);
  13.827 +#endif
  13.828 +		    		continue;
  13.829 +		    	}
  13.830 +			dev2->irq = irq;
  13.831 +			pirq_penalty[irq]++;
  13.832 +			if (dev != dev2)
  13.833 +				printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2));
  13.834 +		}
  13.835 +	}
  13.836 +	return 1;
  13.837 +}
  13.838 +
  13.839 +static void __init pcibios_fixup_irqs(void)
  13.840 +{
  13.841 +	struct pci_dev *dev = NULL;
  13.842 +	u8 pin;
  13.843 +
  13.844 +	DBG("PCI: IRQ fixup\n");
  13.845 +	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
  13.846 +		/*
  13.847 +		 * If the BIOS has set an out of range IRQ number, just ignore it.
  13.848 +		 * Also keep track of which IRQ's are already in use.
  13.849 +		 */
  13.850 +		if (dev->irq >= 16) {
  13.851 +			DBG("%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
  13.852 +			dev->irq = 0;
  13.853 +		}
  13.854 +		/* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
  13.855 +		if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
  13.856 +			pirq_penalty[dev->irq] = 0;
  13.857 +		pirq_penalty[dev->irq]++;
  13.858 +	}
  13.859 +
  13.860 +	dev = NULL;
  13.861 +	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
  13.862 +		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
  13.863 +#ifdef CONFIG_X86_IO_APIC
  13.864 +		/*
  13.865 +		 * Recalculate IRQ numbers if we use the I/O APIC.
  13.866 +		 */
  13.867 +		if (io_apic_assign_pci_irqs)
  13.868 +		{
  13.869 +			int irq;
  13.870 +
  13.871 +			if (pin) {
  13.872 +				pin--;		/* interrupt pins are numbered starting from 1 */
  13.873 +				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
  13.874 +	/*
  13.875 +	 * Busses behind bridges are typically not listed in the MP-table.
  13.876 +	 * In this case we have to look up the IRQ based on the parent bus,
  13.877 +	 * parent slot, and pin number. The SMP code detects such bridged
  13.878 +	 * busses itself so we should get into this branch reliably.
  13.879 +	 */
  13.880 +				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
  13.881 +					struct pci_dev * bridge = dev->bus->self;
  13.882 +
  13.883 +					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
  13.884 +					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
  13.885 +							PCI_SLOT(bridge->devfn), pin);
  13.886 +					if (irq >= 0)
  13.887 +						printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
  13.888 +							pci_name(bridge), 'A' + pin, irq);
  13.889 +				}
  13.890 +				if (irq >= 0) {
  13.891 +					if (use_pci_vector() &&
  13.892 +						!platform_legacy_irq(irq))
  13.893 +						irq = IO_APIC_VECTOR(irq);
  13.894 +
  13.895 +					printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
  13.896 +						pci_name(dev), 'A' + pin, irq);
  13.897 +					dev->irq = irq;
  13.898 +				}
  13.899 +			}
  13.900 +		}
  13.901 +#endif
  13.902 +		/*
  13.903 +		 * Still no IRQ? Try to lookup one...
  13.904 +		 */
  13.905 +		if (pin && !dev->irq)
  13.906 +			pcibios_lookup_irq(dev, 0);
  13.907 +	}
  13.908 +}
  13.909 +
  13.910 +/*
  13.911 + * Work around broken HP Pavilion Notebooks which assign USB to
  13.912 + * IRQ 9 even though it is actually wired to IRQ 11
  13.913 + */
  13.914 +static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d)
  13.915 +{
  13.916 +	if (!broken_hp_bios_irq9) {
  13.917 +		broken_hp_bios_irq9 = 1;
  13.918 +		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
  13.919 +	}
  13.920 +	return 0;
  13.921 +}
  13.922 +
  13.923 +/*
  13.924 + * Work around broken Acer TravelMate 360 Notebooks which assign
  13.925 + * Cardbus to IRQ 11 even though it is actually wired to IRQ 10
  13.926 + */
  13.927 +static int __init fix_acer_tm360_irqrouting(struct dmi_system_id *d)
  13.928 +{
  13.929 +	if (!acer_tm360_irqrouting) {
  13.930 +		acer_tm360_irqrouting = 1;
  13.931 +		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
  13.932 +	}
  13.933 +	return 0;
  13.934 +}
  13.935 +
  13.936 +static struct dmi_system_id __initdata pciirq_dmi_table[] = {
  13.937 +	{
  13.938 +		.callback = fix_broken_hp_bios_irq9,
  13.939 +		.ident = "HP Pavilion N5400 Series Laptop",
  13.940 +		.matches = {
  13.941 +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  13.942 +			DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
  13.943 +			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
  13.944 +			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
  13.945 +		},
  13.946 +	},
  13.947 +	{
  13.948 +		.callback = fix_acer_tm360_irqrouting,
  13.949 +		.ident = "Acer TravelMate 36x Laptop",
  13.950 +		.matches = {
  13.951 +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  13.952 +			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
  13.953 +		},
  13.954 +	},
  13.955 +	{ }
  13.956 +};
  13.957  
  13.958  static int __init pcibios_irq_init(void)
  13.959  {
  13.960 -	int bus;
  13.961 -	physdev_op_t op;
  13.962 -
  13.963  	DBG("PCI: IRQ init\n");
  13.964  
  13.965  	if (pcibios_enable_irq || raw_pci_ops == NULL)
  13.966  		return 0;
  13.967  
  13.968 -	op.cmd = PHYSDEVOP_PCI_PROBE_ROOT_BUSES;
  13.969 -	if (HYPERVISOR_physdev_op(&op) != 0) {
  13.970 -		printk(KERN_WARNING "PCI: System does not support PCI\n");
  13.971 -		return 0;
  13.972 -	}
  13.973 +	dmi_check_system(pciirq_dmi_table);
  13.974 +
  13.975 +	pirq_table = pirq_find_routing_table();
  13.976  
  13.977 -	printk(KERN_INFO "PCI: Probing PCI hardware\n");
  13.978 -	for (bus = 0; bus < 256; bus++)
  13.979 -		if (test_bit(bus, (unsigned long *)
  13.980 -			&op.u.pci_probe_root_buses.busmask[0]))
  13.981 -			(void)pcibios_scan_root(bus);
  13.982 +#ifdef CONFIG_PCI_BIOS
  13.983 +	if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
  13.984 +		pirq_table = pcibios_get_irq_routing_table();
  13.985 +#endif
  13.986 +	if (pirq_table) {
  13.987 +		pirq_peer_trick();
  13.988 +		pirq_find_router(&pirq_router);
  13.989 +		if (pirq_table->exclusive_irqs) {
  13.990 +			int i;
  13.991 +			for (i=0; i<16; i++)
  13.992 +				if (!(pirq_table->exclusive_irqs & (1 << i)))
  13.993 +					pirq_penalty[i] += 100;
  13.994 +		}
  13.995 +		/* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
  13.996 +		if (io_apic_assign_pci_irqs)
  13.997 +			pirq_table = NULL;
  13.998 +	}
  13.999  
 13.1000  	pcibios_enable_irq = pirq_enable_irq;
 13.1001  
 13.1002 +	pcibios_fixup_irqs();
 13.1003  	return 0;
 13.1004  }
 13.1005  
 13.1006 @@ -92,35 +1030,67 @@ void pcibios_penalize_isa_irq(int irq)
 13.1007  
 13.1008  static int pirq_enable_irq(struct pci_dev *dev)
 13.1009  {
 13.1010 -	int err;
 13.1011  	u8 pin;
 13.1012 -	physdev_op_t op;
 13.1013 +	extern int via_interrupt_line_quirk;
 13.1014 +	struct pci_dev *temp_dev;
 13.1015 +
 13.1016 +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 13.1017 +	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
 13.1018 +		char *msg;
 13.1019 +		msg = "";
 13.1020 +		if (io_apic_assign_pci_irqs) {
 13.1021 +			int irq;
 13.1022  
 13.1023 -	/* Inform Xen that we are going to use this device. */
 13.1024 -	op.cmd = PHYSDEVOP_PCI_INITIALISE_DEVICE;
 13.1025 -	op.u.pci_initialise_device.bus  = dev->bus->number;
 13.1026 -	op.u.pci_initialise_device.dev  = PCI_SLOT(dev->devfn);
 13.1027 -	op.u.pci_initialise_device.func = PCI_FUNC(dev->devfn);
 13.1028 -	if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
 13.1029 -		return err;
 13.1030 +			if (pin) {
 13.1031 +				pin--;		/* interrupt pins are numbered starting from 1 */
 13.1032 +				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
 13.1033 +				/*
 13.1034 +				 * Busses behind bridges are typically not listed in the MP-table.
 13.1035 +				 * In this case we have to look up the IRQ based on the parent bus,
 13.1036 +				 * parent slot, and pin number. The SMP code detects such bridged
 13.1037 +				 * busses itself so we should get into this branch reliably.
 13.1038 +				 */
 13.1039 +				temp_dev = dev;
 13.1040 +				while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
 13.1041 +					struct pci_dev * bridge = dev->bus->self;
 13.1042  
 13.1043 -	/* Now we can bind to the very final IRQ line. */
 13.1044 -	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pin);
 13.1045 -	dev->irq = pin;
 13.1046 -
 13.1047 -	/* Sanity-check that an interrupt-producing device is routed
 13.1048 -	 * to an IRQ. */
 13.1049 -	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 13.1050 -	if (pin != 0) {
 13.1051 -		if (dev->irq != 0)
 13.1052 -			printk(KERN_INFO "PCI: Obtained IRQ %d for device %s\n",
 13.1053 -			    dev->irq, dev->slot_name);
 13.1054 +					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
 13.1055 +					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
 13.1056 +							PCI_SLOT(bridge->devfn), pin);
 13.1057 +					if (irq >= 0)
 13.1058 +						printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
 13.1059 +							pci_name(bridge), 'A' + pin, irq);
 13.1060 +					dev = bridge;
 13.1061 +				}
 13.1062 +				dev = temp_dev;
 13.1063 +				if (irq >= 0) {
 13.1064 +#ifdef CONFIG_PCI_MSI
 13.1065 +					if (!platform_legacy_irq(irq))
 13.1066 +						irq = IO_APIC_VECTOR(irq);
 13.1067 +#endif
 13.1068 +					printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
 13.1069 +						pci_name(dev), 'A' + pin, irq);
 13.1070 +					dev->irq = irq;
 13.1071 +					return 0;
 13.1072 +				} else
 13.1073 +					msg = " Probably buggy MP table.";
 13.1074 +			}
 13.1075 +		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
 13.1076 +			msg = "";
 13.1077  		else
 13.1078 -			printk(KERN_WARNING "PCI: No IRQ known for interrupt "
 13.1079 -			    "pin %c of device %s.\n", 'A' + pin - 1,
 13.1080 -			    dev->slot_name);
 13.1081 +			msg = " Please try using pci=biosirq.";
 13.1082 +			
 13.1083 +		/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
 13.1084 +		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
 13.1085 +			return 0;
 13.1086 +			
 13.1087 +		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
 13.1088 +		       'A' + pin - 1, pci_name(dev), msg);
 13.1089  	}
 13.1090 -
 13.1091 +	/* VIA bridges use interrupt line for apic/pci steering across
 13.1092 +	   the V-Link */
 13.1093 +	else if (via_interrupt_line_quirk)
 13.1094 +		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
 13.1095  	return 0;
 13.1096  }
 13.1097  
    14.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c	Tue May 03 12:28:27 2005 +0000
    14.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c	Tue May 03 14:27:54 2005 +0000
    14.3 @@ -4,9 +4,6 @@
    14.4  #include <linux/kernel.h>
    14.5  #include <linux/threads.h>
    14.6  
    14.7 -unsigned int __initdata maxcpus = NR_CPUS;
    14.8 -
    14.9 -
   14.10  /*
   14.11   * the frequency of the profiling timer can be changed
   14.12   * by writing a multiplier value into /proc/profile.
    15.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig	Tue May 03 12:28:27 2005 +0000
    15.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig	Tue May 03 14:27:54 2005 +0000
    15.3 @@ -363,8 +363,6 @@ menu "Power management options"
    15.4  
    15.5  source kernel/power/Kconfig
    15.6  
    15.7 -source "drivers/acpi/Kconfig"
    15.8 -
    15.9  source "arch/x86_64/kernel/cpufreq/Kconfig"
   15.10  
   15.11  endmenu
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/linux-2.6.11-xen-sparse/drivers/acpi/tables.c	Tue May 03 14:27:54 2005 +0000
    16.3 @@ -0,0 +1,610 @@
    16.4 +/*
    16.5 + *  acpi_tables.c - ACPI Boot-Time Table Parsing
    16.6 + *
    16.7 + *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
    16.8 + *
    16.9 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   16.10 + *
   16.11 + *  This program is free software; you can redistribute it and/or modify
   16.12 + *  it under the terms of the GNU General Public License as published by
   16.13 + *  the Free Software Foundation; either version 2 of the License, or
   16.14 + *  (at your option) any later version.
   16.15 + *
   16.16 + *  This program is distributed in the hope that it will be useful,
   16.17 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.18 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.19 + *  GNU General Public License for more details.
   16.20 + *
   16.21 + *  You should have received a copy of the GNU General Public License
   16.22 + *  along with this program; if not, write to the Free Software
   16.23 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   16.24 + *
   16.25 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   16.26 + *
   16.27 + */
   16.28 +
   16.29 +#include <linux/config.h>
   16.30 +#include <linux/init.h>
   16.31 +#include <linux/kernel.h>
   16.32 +#include <linux/sched.h>
   16.33 +#include <linux/smp.h>
   16.34 +#include <linux/string.h>
   16.35 +#include <linux/types.h>
   16.36 +#include <linux/irq.h>
   16.37 +#include <linux/errno.h>
   16.38 +#include <linux/acpi.h>
   16.39 +#include <linux/bootmem.h>
   16.40 +
   16.41 +#define PREFIX			"ACPI: "
   16.42 +
   16.43 +#define ACPI_MAX_TABLES		256
   16.44 +
   16.45 +static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
   16.46 +	[ACPI_TABLE_UNKNOWN]	= "????",
   16.47 +	[ACPI_APIC]		= "APIC",
   16.48 +	[ACPI_BOOT]		= "BOOT",
   16.49 +	[ACPI_DBGP]		= "DBGP",
   16.50 +	[ACPI_DSDT]		= "DSDT",
   16.51 +	[ACPI_ECDT]		= "ECDT",
   16.52 +	[ACPI_ETDT]		= "ETDT",
   16.53 +	[ACPI_FADT]		= "FACP",
   16.54 +	[ACPI_FACS]		= "FACS",
   16.55 +	[ACPI_OEMX]		= "OEM",
   16.56 +	[ACPI_PSDT]		= "PSDT",
   16.57 +	[ACPI_SBST]		= "SBST",
   16.58 +	[ACPI_SLIT]		= "SLIT",
   16.59 +	[ACPI_SPCR]		= "SPCR",
   16.60 +	[ACPI_SRAT]		= "SRAT",
   16.61 +	[ACPI_SSDT]		= "SSDT",
   16.62 +	[ACPI_SPMI]		= "SPMI",
   16.63 +	[ACPI_HPET]		= "HPET",
   16.64 +	[ACPI_MCFG]		= "MCFG",
   16.65 +};
   16.66 +
   16.67 +static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
   16.68 +static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
   16.69 +
   16.70 +/* System Description Table (RSDT/XSDT) */
   16.71 +struct acpi_table_sdt {
   16.72 +	unsigned long		pa;
   16.73 +	enum acpi_table_id	id;
   16.74 +	unsigned long		size;
   16.75 +} __attribute__ ((packed));
   16.76 +
   16.77 +static unsigned long		sdt_pa;		/* Physical Address */
   16.78 +static unsigned long		sdt_count;	/* Table count */
   16.79 +
   16.80 +static struct acpi_table_sdt	sdt_entry[ACPI_MAX_TABLES];
   16.81 +
   16.82 +void
   16.83 +acpi_table_print (
   16.84 +	struct acpi_table_header *header,
   16.85 +	unsigned long		phys_addr)
   16.86 +{
   16.87 +	char			*name = NULL;
   16.88 +
   16.89 +	if (!header)
   16.90 +		return;
   16.91 +
   16.92 +	/* Some table signatures aren't good table names */
   16.93 +
   16.94 +	if (!strncmp((char *) &header->signature,
   16.95 +		acpi_table_signatures[ACPI_APIC],
   16.96 +		sizeof(header->signature))) {
   16.97 +		name = "MADT";
   16.98 +	}
   16.99 +	else if (!strncmp((char *) &header->signature,
  16.100 +		acpi_table_signatures[ACPI_FADT],
  16.101 +		sizeof(header->signature))) {
  16.102 +		name = "FADT";
  16.103 +	}
  16.104 +	else
  16.105 +		name = header->signature;
  16.106 +
  16.107 +	printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
  16.108 +		name, header->revision, header->oem_id,
  16.109 +		header->oem_table_id, header->oem_revision,
  16.110 +		header->asl_compiler_id, header->asl_compiler_revision,
  16.111 +		(void *) phys_addr);
  16.112 +}
  16.113 +
  16.114 +
  16.115 +void
  16.116 +acpi_table_print_madt_entry (
  16.117 +	acpi_table_entry_header	*header)
  16.118 +{
  16.119 +	if (!header)
  16.120 +		return;
  16.121 +
  16.122 +	switch (header->type) {
  16.123 +
  16.124 +	case ACPI_MADT_LAPIC:
  16.125 +	{
  16.126 +		struct acpi_table_lapic *p =
  16.127 +			(struct acpi_table_lapic*) header;
  16.128 +		printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
  16.129 +			p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled");
  16.130 +	}
  16.131 +		break;
  16.132 +
  16.133 +	case ACPI_MADT_IOAPIC:
  16.134 +	{
  16.135 +		struct acpi_table_ioapic *p =
  16.136 +			(struct acpi_table_ioapic*) header;
  16.137 +		printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
  16.138 +			p->id, p->address, p->global_irq_base);
  16.139 +	}
  16.140 +		break;
  16.141 +
  16.142 +	case ACPI_MADT_INT_SRC_OVR:
  16.143 +	{
  16.144 +		struct acpi_table_int_src_ovr *p =
  16.145 +			(struct acpi_table_int_src_ovr*) header;
  16.146 +		printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
  16.147 +			p->bus, p->bus_irq, p->global_irq,
  16.148 +			mps_inti_flags_polarity[p->flags.polarity],
  16.149 +			mps_inti_flags_trigger[p->flags.trigger]);
  16.150 +		if(p->flags.reserved)
  16.151 +			printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
  16.152 +				p->flags.reserved);
  16.153 +
  16.154 +	}
  16.155 +		break;
  16.156 +
  16.157 +	case ACPI_MADT_NMI_SRC:
  16.158 +	{
  16.159 +		struct acpi_table_nmi_src *p =
  16.160 +			(struct acpi_table_nmi_src*) header;
  16.161 +		printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n",
  16.162 +			mps_inti_flags_polarity[p->flags.polarity],
  16.163 +			mps_inti_flags_trigger[p->flags.trigger], p->global_irq);
  16.164 +	}
  16.165 +		break;
  16.166 +
  16.167 +	case ACPI_MADT_LAPIC_NMI:
  16.168 +	{
  16.169 +		struct acpi_table_lapic_nmi *p =
  16.170 +			(struct acpi_table_lapic_nmi*) header;
  16.171 +		printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
  16.172 +			p->acpi_id,
  16.173 +			mps_inti_flags_polarity[p->flags.polarity],
  16.174 +			mps_inti_flags_trigger[p->flags.trigger], p->lint);
  16.175 +	}
  16.176 +		break;
  16.177 +
  16.178 +	case ACPI_MADT_LAPIC_ADDR_OVR:
  16.179 +	{
  16.180 +		struct acpi_table_lapic_addr_ovr *p =
  16.181 +			(struct acpi_table_lapic_addr_ovr*) header;
  16.182 +		printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n",
  16.183 +			(void *) (unsigned long) p->address);
  16.184 +	}
  16.185 +		break;
  16.186 +
  16.187 +	case ACPI_MADT_IOSAPIC:
  16.188 +	{
  16.189 +		struct acpi_table_iosapic *p =
  16.190 +			(struct acpi_table_iosapic*) header;
  16.191 +		printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
  16.192 +			p->id, (void *) (unsigned long) p->address, p->global_irq_base);
  16.193 +	}
  16.194 +		break;
  16.195 +
  16.196 +	case ACPI_MADT_LSAPIC:
  16.197 +	{
  16.198 +		struct acpi_table_lsapic *p =
  16.199 +			(struct acpi_table_lsapic*) header;
  16.200 +		printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
  16.201 +			p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled");
  16.202 +	}
  16.203 +		break;
  16.204 +
  16.205 +	case ACPI_MADT_PLAT_INT_SRC:
  16.206 +	{
  16.207 +		struct acpi_table_plat_int_src *p =
  16.208 +			(struct acpi_table_plat_int_src*) header;
  16.209 +		printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
  16.210 +			mps_inti_flags_polarity[p->flags.polarity],
  16.211 +			mps_inti_flags_trigger[p->flags.trigger],
  16.212 +			p->type, p->id, p->eid, p->iosapic_vector, p->global_irq);
  16.213 +	}
  16.214 +		break;
  16.215 +
  16.216 +	default:
  16.217 +		printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n",
  16.218 +			header->type);
  16.219 +		break;
  16.220 +	}
  16.221 +}
  16.222 +
  16.223 +
  16.224 +static int
  16.225 +acpi_table_compute_checksum (
  16.226 +	void			*table_pointer,
  16.227 +	unsigned long		length)
  16.228 +{
  16.229 +	u8			*p = (u8 *) table_pointer;
  16.230 +	unsigned long		remains = length;
  16.231 +	unsigned long		sum = 0;
  16.232 +
  16.233 +	if (!p || !length)
  16.234 +		return -EINVAL;
  16.235 +
  16.236 +	while (remains--)
  16.237 +		sum += *p++;
  16.238 +
  16.239 +	return (sum & 0xFF);
  16.240 +}
  16.241 +
  16.242 +/*
  16.243 + * acpi_get_table_header_early()
  16.244 + * for acpi_blacklisted(), acpi_table_get_sdt()
  16.245 + */
  16.246 +int __init
  16.247 +acpi_get_table_header_early (
  16.248 +	enum acpi_table_id	id,
  16.249 +	struct acpi_table_header **header)
  16.250 +{
  16.251 +	unsigned int i;
  16.252 +	enum acpi_table_id temp_id;
  16.253 +
  16.254 +	/* DSDT is different from the rest */
  16.255 +	if (id == ACPI_DSDT)
  16.256 +		temp_id = ACPI_FADT;
  16.257 +	else
  16.258 +		temp_id = id;
  16.259 +
  16.260 +	/* Locate the table. */
  16.261 +
  16.262 +	for (i = 0; i < sdt_count; i++) {
  16.263 +		if (sdt_entry[i].id != temp_id)
  16.264 +			continue;
  16.265 +		*header = (void *)
  16.266 +			__acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
  16.267 +		if (!*header) {
  16.268 +			printk(KERN_WARNING PREFIX "Unable to map %s\n",
  16.269 +			       acpi_table_signatures[temp_id]);
  16.270 +			return -ENODEV;
  16.271 +		}
  16.272 +		break;
  16.273 +	}
  16.274 +
  16.275 +	if (!*header) {
  16.276 +		printk(KERN_WARNING PREFIX "%s not present\n",
  16.277 +		       acpi_table_signatures[id]);
  16.278 +		return -ENODEV;
  16.279 +	}
  16.280 +
  16.281 +	/* Map the DSDT header via the pointer in the FADT */
  16.282 +	if (id == ACPI_DSDT) {
  16.283 +		struct fadt_descriptor_rev2 *fadt = (struct fadt_descriptor_rev2 *) *header;
  16.284 +
  16.285 +		if (fadt->revision == 3 && fadt->Xdsdt) {
  16.286 +			*header = (void *) __acpi_map_table(fadt->Xdsdt,
  16.287 +					sizeof(struct acpi_table_header));
  16.288 +		} else if (fadt->V1_dsdt) {
  16.289 +			*header = (void *) __acpi_map_table(fadt->V1_dsdt,
  16.290 +					sizeof(struct acpi_table_header));
  16.291 +		} else
  16.292 +			*header = NULL;
  16.293 +
  16.294 +		if (!*header) {
  16.295 +			printk(KERN_WARNING PREFIX "Unable to map DSDT\n");
  16.296 +			return -ENODEV;
  16.297 +		}
  16.298 +	}
  16.299 +
  16.300 +	return 0;
  16.301 +}
  16.302 +	 
  16.303 +
  16.304 +int __init
  16.305 +acpi_table_parse_madt_family (
  16.306 +	enum acpi_table_id	id,
  16.307 +	unsigned long		madt_size,
  16.308 +	int			entry_id,
  16.309 +	acpi_madt_entry_handler	handler,
  16.310 +	unsigned int		max_entries)
  16.311 +{
  16.312 +	void			*madt = NULL;
  16.313 +	acpi_table_entry_header	*entry;
  16.314 +	unsigned int		count = 0;
  16.315 +	unsigned long		madt_end;
  16.316 +	unsigned int		i;
  16.317 +
  16.318 +	if (!handler)
  16.319 +		return -EINVAL;
  16.320 +
  16.321 +	/* Locate the MADT (if exists). There should only be one. */
  16.322 +
  16.323 +	for (i = 0; i < sdt_count; i++) {
  16.324 +		if (sdt_entry[i].id != id)
  16.325 +			continue;
  16.326 +		madt = (void *)
  16.327 +			__acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
  16.328 +		if (!madt) {
  16.329 +			printk(KERN_WARNING PREFIX "Unable to map %s\n",
  16.330 +			       acpi_table_signatures[id]);
  16.331 +			return -ENODEV;
  16.332 +		}
  16.333 +		break;
  16.334 +	}
  16.335 +
  16.336 +	if (!madt) {
  16.337 +		printk(KERN_WARNING PREFIX "%s not present\n",
  16.338 +		       acpi_table_signatures[id]);
  16.339 +		return -ENODEV;
  16.340 +	}
  16.341 +
  16.342 +	madt_end = (unsigned long) madt + sdt_entry[i].size;
  16.343 +
  16.344 +	/* Parse all entries looking for a match. */
  16.345 +
  16.346 +	entry = (acpi_table_entry_header *)
  16.347 +		((unsigned long) madt + madt_size);
  16.348 +
  16.349 +	while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
  16.350 +		if (entry->type == entry_id &&
  16.351 +		    (!max_entries || count++ < max_entries))
  16.352 +			if (handler(entry, madt_end))
  16.353 +				return -EINVAL;
  16.354 +
  16.355 +		entry = (acpi_table_entry_header *)
  16.356 +			((unsigned long) entry + entry->length);
  16.357 +	}
  16.358 +	if (max_entries && count > max_entries) {
  16.359 +		printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
  16.360 +		       "%i found\n", acpi_table_signatures[id], entry_id,
  16.361 +		       count - max_entries, count);
  16.362 +	}
  16.363 +
  16.364 +	return count;
  16.365 +}
  16.366 +
  16.367 +
  16.368 +int __init
  16.369 +acpi_table_parse_madt (
  16.370 +	enum acpi_madt_entry_id	id,
  16.371 +	acpi_madt_entry_handler	handler,
  16.372 +	unsigned int max_entries)
  16.373 +{
  16.374 +	return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt),
  16.375 +					    id, handler, max_entries);
  16.376 +}
  16.377 +
  16.378 +
  16.379 +int __init
  16.380 +acpi_table_parse (
  16.381 +	enum acpi_table_id	id,
  16.382 +	acpi_table_handler	handler)
  16.383 +{
  16.384 +	int			count = 0;
  16.385 +	unsigned int		i = 0;
  16.386 +
  16.387 +	if (!handler)
  16.388 +		return -EINVAL;
  16.389 +
  16.390 +	for (i = 0; i < sdt_count; i++) {
  16.391 +		if (sdt_entry[i].id != id)
  16.392 +			continue;
  16.393 +		count++;
  16.394 +		if (count == 1)
  16.395 +			handler(sdt_entry[i].pa, sdt_entry[i].size);
  16.396 +
  16.397 +		else
  16.398 +			printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n",
  16.399 +				count, acpi_table_signatures[id]);
  16.400 +	}
  16.401 +
  16.402 +	return count;
  16.403 +}
  16.404 +
  16.405 +
  16.406 +static int __init
  16.407 +acpi_table_get_sdt (
  16.408 +	struct acpi_table_rsdp	*rsdp)
  16.409 +{
  16.410 +	struct acpi_table_header *header = NULL;
  16.411 +	unsigned int		i, id = 0;
  16.412 +
  16.413 +	if (!rsdp)
  16.414 +		return -EINVAL;
  16.415 +
  16.416 +	/* First check XSDT (but only on ACPI 2.0-compatible systems) */
  16.417 +
  16.418 +	if ((rsdp->revision >= 2) &&
  16.419 +		(((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) {
  16.420 +			
  16.421 +		struct acpi_table_xsdt	*mapped_xsdt = NULL;
  16.422 +
  16.423 +		sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address;
  16.424 +
  16.425 +		/* map in just the header */
  16.426 +		header = (struct acpi_table_header *)
  16.427 +			__acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
  16.428 +
  16.429 +		if (!header) {
  16.430 +			printk(KERN_WARNING PREFIX "Unable to map XSDT header\n");
  16.431 +			return -ENODEV;
  16.432 +		}
  16.433 +
  16.434 +		/* remap in the entire table before processing */
  16.435 +		mapped_xsdt = (struct acpi_table_xsdt *)
  16.436 +			__acpi_map_table(sdt_pa, header->length);
  16.437 +		if (!mapped_xsdt) {
  16.438 +			printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
  16.439 +			return -ENODEV;
  16.440 +		}
  16.441 +		header = &mapped_xsdt->header;
  16.442 +
  16.443 +		if (strncmp(header->signature, "XSDT", 4)) {
  16.444 +			printk(KERN_WARNING PREFIX "XSDT signature incorrect\n");
  16.445 +			return -ENODEV;
  16.446 +		}
  16.447 +
  16.448 +		if (acpi_table_compute_checksum(header, header->length)) {
  16.449 +			printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n");
  16.450 +			return -ENODEV;
  16.451 +		}
  16.452 +
  16.453 +		sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3;
  16.454 +		if (sdt_count > ACPI_MAX_TABLES) {
  16.455 +			printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n",
  16.456 +				(sdt_count - ACPI_MAX_TABLES));
  16.457 +			sdt_count = ACPI_MAX_TABLES;
  16.458 +		}
  16.459 +
  16.460 +		for (i = 0; i < sdt_count; i++)
  16.461 +			sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
  16.462 +	}
  16.463 +
  16.464 +	/* Then check RSDT */
  16.465 +
  16.466 +	else if (rsdp->rsdt_address) {
  16.467 +
  16.468 +		struct acpi_table_rsdt	*mapped_rsdt = NULL;
  16.469 +
  16.470 +		sdt_pa = rsdp->rsdt_address;
  16.471 +
  16.472 +		/* map in just the header */
  16.473 +		header = (struct acpi_table_header *)
  16.474 +			__acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
  16.475 +		if (!header) {
  16.476 +			printk(KERN_WARNING PREFIX "Unable to map RSDT header\n");
  16.477 +			return -ENODEV;
  16.478 +		}
  16.479 +
  16.480 +		/* remap in the entire table before processing */
  16.481 +		mapped_rsdt = (struct acpi_table_rsdt *)
  16.482 +			__acpi_map_table(sdt_pa, header->length);
  16.483 +		if (!mapped_rsdt) {
  16.484 +			printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
  16.485 +			return -ENODEV;
  16.486 +		}
  16.487 +		header = &mapped_rsdt->header;
  16.488 +
  16.489 +		if (strncmp(header->signature, "RSDT", 4)) {
  16.490 +			printk(KERN_WARNING PREFIX "RSDT signature incorrect\n");
  16.491 +			return -ENODEV;
  16.492 +		}
  16.493 +
  16.494 +		if (acpi_table_compute_checksum(header, header->length)) {
  16.495 +			printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n");
  16.496 +			return -ENODEV;
  16.497 +		}
  16.498 +
  16.499 +		sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2;
  16.500 +		if (sdt_count > ACPI_MAX_TABLES) {
  16.501 +			printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n",
  16.502 +				(sdt_count - ACPI_MAX_TABLES));
  16.503 +			sdt_count = ACPI_MAX_TABLES;
  16.504 +		}
  16.505 +
  16.506 +		for (i = 0; i < sdt_count; i++)
  16.507 +			sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
  16.508 +	}
  16.509 +
  16.510 +	else {
  16.511 +		printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n");
  16.512 +		return -ENODEV;
  16.513 +	}
  16.514 +
  16.515 +	acpi_table_print(header, sdt_pa);
  16.516 +
  16.517 +	for (i = 0; i < sdt_count; i++) {
  16.518 +
  16.519 +		/* map in just the header */
  16.520 +		header = (struct acpi_table_header *)
  16.521 +			__acpi_map_table(sdt_entry[i].pa,
  16.522 +				sizeof(struct acpi_table_header));
  16.523 +		if (!header)
  16.524 +			continue;
  16.525 +
  16.526 +		/* remap in the entire table before processing */
  16.527 +		header = (struct acpi_table_header *)
  16.528 +			__acpi_map_table(sdt_entry[i].pa,
  16.529 +				header->length);
  16.530 +		if (!header)
  16.531 +			continue;
  16.532 +	               
  16.533 +		acpi_table_print(header, sdt_entry[i].pa);
  16.534 +
  16.535 +		if (acpi_table_compute_checksum(header, header->length)) {
  16.536 +			printk(KERN_WARNING "  >>> ERROR: Invalid checksum\n");
  16.537 +			continue;
  16.538 +		}
  16.539 +
  16.540 +		sdt_entry[i].size = header->length;
  16.541 +
  16.542 +		for (id = 0; id < ACPI_TABLE_COUNT; id++) {
  16.543 +			if (!strncmp((char *) &header->signature,
  16.544 +				acpi_table_signatures[id],
  16.545 +				sizeof(header->signature))) {
  16.546 +				sdt_entry[i].id = id;
  16.547 +			}
  16.548 +		}
  16.549 +	}
  16.550 +
  16.551 +	/* 
  16.552 +	 * The DSDT is *not* in the RSDT (why not? no idea.) but we want
  16.553 +	 * to print its info, because this is what people usually blacklist
  16.554 +	 * against. Unfortunately, we don't know the phys_addr, so just
  16.555 +	 * print 0. Maybe no one will notice.
  16.556 +	 */
  16.557 +	if(!acpi_get_table_header_early(ACPI_DSDT, &header))
  16.558 +		acpi_table_print(header, 0);
  16.559 +
  16.560 +	return 0;
  16.561 +}
  16.562 +
  16.563 +/*
  16.564 + * acpi_table_init()
  16.565 + *
  16.566 + * find RSDP, find and checksum SDT/XSDT.
  16.567 + * checksum all tables, print SDT/XSDT
  16.568 + * 
  16.569 + * result: sdt_entry[] is initialized
  16.570 + */
  16.571 +
  16.572 +int __init
  16.573 +acpi_table_init (void)
  16.574 +{
  16.575 +	struct acpi_table_rsdp	*rsdp = NULL;
  16.576 +	unsigned long		rsdp_phys = 0;
  16.577 +	int			result = 0;
  16.578 +
  16.579 +	/* Locate and map the Root System Description Table (RSDP) */
  16.580 +
  16.581 +	rsdp_phys = acpi_find_rsdp();
  16.582 +	if (!rsdp_phys) {
  16.583 +		printk(KERN_ERR PREFIX "Unable to locate RSDP\n");
  16.584 +		return -ENODEV;
  16.585 +	}
  16.586 +
  16.587 +        rsdp = (struct acpi_table_rsdp *) (__fix_to_virt(FIX_ACPI_RSDP_PAGE)
  16.588 +                                           + (rsdp_phys & ~PAGE_MASK));
  16.589 +	if (!rsdp) {
  16.590 +		printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
  16.591 +		return -ENODEV;
  16.592 +	}
  16.593 +
  16.594 +	printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s                                ) @ 0x%p\n",
  16.595 +		rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
  16.596 +
  16.597 +	if (rsdp->revision < 2)
  16.598 +		result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp));
  16.599 +	else
  16.600 +		result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length);
  16.601 +
  16.602 +	if (result) {
  16.603 +		printk(KERN_WARNING "  >>> ERROR: Invalid checksum\n");
  16.604 +		return -ENODEV;
  16.605 +	}
  16.606 +
  16.607 +	/* Locate and map the System Description table (RSDT/XSDT) */
  16.608 +
  16.609 +	if (acpi_table_get_sdt(rsdp))
  16.610 +		return -ENODEV;
  16.611 +
  16.612 +	return 0;
  16.613 +}
    17.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/fixmap.h	Tue May 03 12:28:27 2005 +0000
    17.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/fixmap.h	Tue May 03 14:27:54 2005 +0000
    17.3 @@ -80,6 +80,7 @@ enum fixed_addresses {
    17.4  #ifdef CONFIG_ACPI_BOOT
    17.5  	FIX_ACPI_BEGIN,
    17.6  	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
    17.7 +        FIX_ACPI_RSDP_PAGE,
    17.8  #endif
    17.9  #ifdef CONFIG_PCI_MMCONFIG
   17.10  	FIX_PCIE_MCFG,
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io_apic.h	Tue May 03 14:27:54 2005 +0000
    18.3 @@ -0,0 +1,230 @@
    18.4 +#ifndef __ASM_IO_APIC_H
    18.5 +#define __ASM_IO_APIC_H
    18.6 +
    18.7 +#include <linux/config.h>
    18.8 +#include <asm/types.h>
    18.9 +#include <asm/mpspec.h>
   18.10 +
   18.11 +#include <asm-xen/xen-public/xen.h>
   18.12 +#include <asm-xen/xen-public/physdev.h>
   18.13 +
   18.14 +/*
   18.15 + * Intel IO-APIC support for SMP and UP systems.
   18.16 + *
   18.17 + * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
   18.18 + */
   18.19 +
   18.20 +#ifdef CONFIG_X86_IO_APIC
   18.21 +
   18.22 +#ifdef CONFIG_PCI_MSI
   18.23 +static inline int use_pci_vector(void)	{return 1;}
   18.24 +static inline void disable_edge_ioapic_vector(unsigned int vector) { }
   18.25 +static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
   18.26 +static inline void end_edge_ioapic_vector (unsigned int vector) { }
   18.27 +#define startup_level_ioapic	startup_level_ioapic_vector
   18.28 +#define shutdown_level_ioapic	mask_IO_APIC_vector
   18.29 +#define enable_level_ioapic	unmask_IO_APIC_vector
   18.30 +#define disable_level_ioapic	mask_IO_APIC_vector
   18.31 +#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector
   18.32 +#define end_level_ioapic	end_level_ioapic_vector
   18.33 +#define set_ioapic_affinity	set_ioapic_affinity_vector
   18.34 +
   18.35 +#define startup_edge_ioapic 	startup_edge_ioapic_vector
   18.36 +#define shutdown_edge_ioapic 	disable_edge_ioapic_vector
   18.37 +#define enable_edge_ioapic 	unmask_IO_APIC_vector
   18.38 +#define disable_edge_ioapic 	disable_edge_ioapic_vector
   18.39 +#define ack_edge_ioapic 	ack_edge_ioapic_vector
   18.40 +#define end_edge_ioapic 	end_edge_ioapic_vector
   18.41 +#else
   18.42 +static inline int use_pci_vector(void)	{return 0;}
   18.43 +static inline void disable_edge_ioapic_irq(unsigned int irq) { }
   18.44 +static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { }
   18.45 +static inline void end_edge_ioapic_irq (unsigned int irq) { }
   18.46 +#define startup_level_ioapic	startup_level_ioapic_irq
   18.47 +#define shutdown_level_ioapic	mask_IO_APIC_irq
   18.48 +#define enable_level_ioapic	unmask_IO_APIC_irq
   18.49 +#define disable_level_ioapic	mask_IO_APIC_irq
   18.50 +#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq
   18.51 +#define end_level_ioapic	end_level_ioapic_irq
   18.52 +#define set_ioapic_affinity	set_ioapic_affinity_irq
   18.53 +
   18.54 +#define startup_edge_ioapic 	startup_edge_ioapic_irq
   18.55 +#define shutdown_edge_ioapic 	disable_edge_ioapic_irq
   18.56 +#define enable_edge_ioapic 	unmask_IO_APIC_irq
   18.57 +#define disable_edge_ioapic 	disable_edge_ioapic_irq
   18.58 +#define ack_edge_ioapic 	ack_edge_ioapic_irq
   18.59 +#define end_edge_ioapic 	end_edge_ioapic_irq
   18.60 +#endif
   18.61 +
   18.62 +#define IO_APIC_BASE(idx) \
   18.63 +		((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
   18.64 +		+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
   18.65 +
   18.66 +/*
   18.67 + * The structure of the IO-APIC:
   18.68 + */
   18.69 +union IO_APIC_reg_00 {
   18.70 +	u32	raw;
   18.71 +	struct {
   18.72 +		u32	__reserved_2	: 14,
   18.73 +			LTS		:  1,
   18.74 +			delivery_type	:  1,
   18.75 +			__reserved_1	:  8,
   18.76 +			ID		:  8;
   18.77 +	} __attribute__ ((packed)) bits;
   18.78 +};
   18.79 +
   18.80 +union IO_APIC_reg_01 {
   18.81 +	u32	raw;
   18.82 +	struct {
   18.83 +		u32	version		:  8,
   18.84 +			__reserved_2	:  7,
   18.85 +			PRQ		:  1,
   18.86 +			entries		:  8,
   18.87 +			__reserved_1	:  8;
   18.88 +	} __attribute__ ((packed)) bits;
   18.89 +};
   18.90 +
   18.91 +union IO_APIC_reg_02 {
   18.92 +	u32	raw;
   18.93 +	struct {
   18.94 +		u32	__reserved_2	: 24,
   18.95 +			arbitration	:  4,
   18.96 +			__reserved_1	:  4;
   18.97 +	} __attribute__ ((packed)) bits;
   18.98 +};
   18.99 +
  18.100 +union IO_APIC_reg_03 {
  18.101 +	u32	raw;
  18.102 +	struct {
  18.103 +		u32	boot_DT		:  1,
  18.104 +			__reserved_1	: 31;
  18.105 +	} __attribute__ ((packed)) bits;
  18.106 +};
  18.107 +
  18.108 +/*
  18.109 + * # of IO-APICs and # of IRQ routing registers
  18.110 + */
  18.111 +extern int nr_ioapics;
  18.112 +extern int nr_ioapic_registers[MAX_IO_APICS];
  18.113 +
  18.114 +enum ioapic_irq_destination_types {
  18.115 +	dest_Fixed = 0,
  18.116 +	dest_LowestPrio = 1,
  18.117 +	dest_SMI = 2,
  18.118 +	dest__reserved_1 = 3,
  18.119 +	dest_NMI = 4,
  18.120 +	dest_INIT = 5,
  18.121 +	dest__reserved_2 = 6,
  18.122 +	dest_ExtINT = 7
  18.123 +};
  18.124 +
  18.125 +struct IO_APIC_route_entry {
  18.126 +	__u32	vector		:  8,
  18.127 +		delivery_mode	:  3,	/* 000: FIXED
  18.128 +					 * 001: lowest prio
  18.129 +					 * 111: ExtINT
  18.130 +					 */
  18.131 +		dest_mode	:  1,	/* 0: physical, 1: logical */
  18.132 +		delivery_status	:  1,
  18.133 +		polarity	:  1,
  18.134 +		irr		:  1,
  18.135 +		trigger		:  1,	/* 0: edge, 1: level */
  18.136 +		mask		:  1,	/* 0: enabled, 1: disabled */
  18.137 +		__reserved_2	: 15;
  18.138 +
  18.139 +	union {		struct { __u32
  18.140 +					__reserved_1	: 24,
  18.141 +					physical_dest	:  4,
  18.142 +					__reserved_2	:  4;
  18.143 +			} physical;
  18.144 +
  18.145 +			struct { __u32
  18.146 +					__reserved_1	: 24,
  18.147 +					logical_dest	:  8;
  18.148 +			} logical;
  18.149 +	} dest;
  18.150 +
  18.151 +} __attribute__ ((packed));
  18.152 +
  18.153 +/*
  18.154 + * MP-BIOS irq configuration table structures:
  18.155 + */
  18.156 +
  18.157 +/* I/O APIC entries */
  18.158 +extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
  18.159 +
  18.160 +/* # of MP IRQ source entries */
  18.161 +extern int mp_irq_entries;
  18.162 +
  18.163 +/* MP IRQ source entries */
  18.164 +extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
  18.165 +
  18.166 +/* non-0 if default (table-less) MP configuration */
  18.167 +extern int mpc_default_type;
  18.168 +
  18.169 +static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
  18.170 +{
  18.171 +        physdev_op_t op;
  18.172 +        int ret;
  18.173 +
  18.174 +        op.cmd = PHYSDEVOP_APIC_READ;
  18.175 +        op.u.apic_op.apic = apic;
  18.176 +        op.u.apic_op.offset = reg;
  18.177 +        ret = HYPERVISOR_physdev_op(&op);
  18.178 +        if (ret)
  18.179 +                return ret;
  18.180 +        return op.u.apic_op.value;
  18.181 +}
  18.182 +
  18.183 +static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
  18.184 +{
  18.185 +        physdev_op_t op;
  18.186 +        int ret;
  18.187 +
  18.188 +        op.cmd = PHYSDEVOP_APIC_WRITE;
  18.189 +        op.u.apic_op.apic = apic;
  18.190 +        op.u.apic_op.offset = reg;
  18.191 +        op.u.apic_op.value = value;
  18.192 +        ret = HYPERVISOR_physdev_op(&op);
  18.193 +}
  18.194 +
  18.195 +/*
  18.196 + * Re-write a value: to be used for read-modify-write
  18.197 + * cycles where the read already set up the index register.
  18.198 + *
  18.199 + * Older SiS APIC requires we rewrite the index regiser
  18.200 + */
  18.201 +extern int sis_apic_bug;
  18.202 +static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
  18.203 +{
  18.204 +	if (sis_apic_bug)
  18.205 +		*IO_APIC_BASE(apic) = reg;
  18.206 +	*(IO_APIC_BASE(apic)+4) = value;
  18.207 +}
  18.208 +
  18.209 +/* 1 if "noapic" boot option passed */
  18.210 +extern int skip_ioapic_setup;
  18.211 +
  18.212 +/*
  18.213 + * If we use the IO-APIC for IRQ routing, disable automatic
  18.214 + * assignment of PCI IRQ's.
  18.215 + */
  18.216 +#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
  18.217 +
  18.218 +#ifdef CONFIG_ACPI_BOOT
  18.219 +extern int io_apic_get_unique_id (int ioapic, int apic_id);
  18.220 +extern int io_apic_get_version (int ioapic);
  18.221 +extern int io_apic_get_redir_entries (int ioapic);
  18.222 +extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low);
  18.223 +#endif /*CONFIG_ACPI_BOOT*/
  18.224 +
  18.225 +extern int (*ioapic_renumber_irq)(int ioapic, int irq);
  18.226 +
  18.227 +#else  /* !CONFIG_X86_IO_APIC */
  18.228 +#define io_apic_assign_pci_irqs 0
  18.229 +#endif
  18.230 +
  18.231 +extern int assign_irq_vector(int irq);
  18.232 +
  18.233 +#endif
    19.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Tue May 03 12:28:27 2005 +0000
    19.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Tue May 03 14:27:54 2005 +0000
    19.3 @@ -59,6 +59,9 @@
    19.4  #define LOCAL_TIMER_VECTOR	0xef
    19.5  #endif
    19.6  
    19.7 +#define SPURIOUS_APIC_VECTOR	0xff
    19.8 +#define ERROR_APIC_VECTOR	0xfe
    19.9 +
   19.10  /*
   19.11   * First APIC vector available to drivers: (vectors 0x30-0xee)
   19.12   * we start at 0x31 to spread out vectors evenly between priority
    20.1 --- a/xen/Rules.mk	Tue May 03 12:28:27 2005 +0000
    20.2 +++ b/xen/Rules.mk	Tue May 03 14:27:54 2005 +0000
    20.3 @@ -28,7 +28,6 @@ OBJS    += $(patsubst %.c,%.o,$(C_SRCS))
    20.4  ALL_OBJS := $(BASEDIR)/common/common.o
    20.5  ALL_OBJS += $(BASEDIR)/drivers/char/driver.o
    20.6  ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o
    20.7 -ALL_OBJS += $(BASEDIR)/drivers/pci/driver.o
    20.8  ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o
    20.9  
   20.10  
    21.1 --- a/xen/arch/x86/Makefile	Tue May 03 12:28:27 2005 +0000
    21.2 +++ b/xen/arch/x86/Makefile	Tue May 03 14:27:54 2005 +0000
    21.3 @@ -11,6 +11,8 @@ ifneq ($(crash_debug),y)
    21.4  OBJS := $(patsubst cdb%.o,,$(OBJS))
    21.5  endif
    21.6  
    21.7 +OBJS := $(filter-out pci%,$(OBJS))
    21.8 +
    21.9  default: $(TARGET)
   21.10  
   21.11  $(TARGET): $(TARGET)-syms boot/mkelf32
    22.1 --- a/xen/arch/x86/io_apic.c	Tue May 03 12:28:27 2005 +0000
    22.2 +++ b/xen/arch/x86/io_apic.c	Tue May 03 14:27:54 2005 +0000
    22.3 @@ -619,7 +619,7 @@ int irq_vector[NR_IRQS] = { FIRST_DEVICE
    22.4  int vector_irq[256];
    22.5  #endif
    22.6  
    22.7 -static int __init assign_irq_vector(int irq)
    22.8 +int assign_irq_vector(int irq)
    22.9  {
   22.10  	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
   22.11  	if (IO_APIC_VECTOR(irq) > 0)
    23.1 --- a/xen/common/physdev.c	Tue May 03 12:28:27 2005 +0000
    23.2 +++ b/xen/common/physdev.c	Tue May 03 14:27:54 2005 +0000
    23.3 @@ -491,6 +491,7 @@ static int do_rom_address_access(phys_de
    23.4  }
    23.5  #endif /* SLOPPY_CHECKING */
    23.6  
    23.7 +#ifdef CONFIG_PCI
    23.8  /*
    23.9   * Handle a PCI config space read access if the domain has access privileges.
   23.10   */
   23.11 @@ -635,23 +636,24 @@ static long pci_probe_root_buses(u32 *bu
   23.12  
   23.13      return 0;
   23.14  }
   23.15 -
   23.16 +#endif
   23.17  
   23.18  /*
   23.19   * Demuxing hypercall.
   23.20   */
   23.21  long do_physdev_op(physdev_op_t *uop)
   23.22  {
   23.23 -    phys_dev_t  *pdev;
   23.24      physdev_op_t op;
   23.25      long         ret;
   23.26 -    int          irq;
   23.27 +    u32          apic, irq;
   23.28 +    u32          address, val;
   23.29  
   23.30      if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   23.31          return -EFAULT;
   23.32  
   23.33      switch ( op.cmd )
   23.34      {
   23.35 +#ifdef CONFIG_PCI
   23.36      case PHYSDEVOP_PCI_CFGREG_READ:
   23.37          ret = pci_cfgreg_read(op.u.pci_cfgreg_read.bus,
   23.38                                op.u.pci_cfgreg_read.dev, 
   23.39 @@ -682,7 +684,7 @@ long do_physdev_op(physdev_op_t *uop)
   23.40      case PHYSDEVOP_PCI_PROBE_ROOT_BUSES:
   23.41          ret = pci_probe_root_buses(op.u.pci_probe_root_buses.busmask);
   23.42          break;
   23.43 -
   23.44 +#endif
   23.45      case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
   23.46          ret = pirq_guest_unmask(current->domain);
   23.47          break;
   23.48 @@ -698,7 +700,45 @@ long do_physdev_op(physdev_op_t *uop)
   23.49              op.u.irq_status_query.flags |= PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY;
   23.50          ret = 0;
   23.51          break;
   23.52 +#ifdef __ARCH_HAS_IOAPIC
   23.53 +    case PHYSDEVOP_APIC_READ:
   23.54 +        if ( !IS_PRIV(current->domain) )
   23.55 +                return -EPERM;
   23.56  
   23.57 +        apic = op.u.apic_op.apic;
   23.58 +        address = op.u.apic_op.offset;
   23.59 +        ret = -EINVAL;
   23.60 +        if (apic >= nr_ioapics)
   23.61 +            break;
   23.62 +        val = io_apic_read(apic, address);
   23.63 +        DPRINTK("ioapic read: %x = %x\n", address, val);
   23.64 +        op.u.apic_op.value = val;
   23.65 +        ret = 0;
   23.66 +        break;
   23.67 +    case PHYSDEVOP_APIC_WRITE:
   23.68 +        if ( !IS_PRIV(current->domain) )
   23.69 +                return -EPERM;
   23.70 +
   23.71 +        apic = op.u.apic_op.apic;
   23.72 +        address = op.u.apic_op.offset;
   23.73 +        val = op.u.apic_op.value;
   23.74 +        ret = -EINVAL;
   23.75 +        if (apic >= nr_ioapics)
   23.76 +            break;
   23.77 +
   23.78 +        DPRINTK("ioapic write: %x = %x\n", address, val);
   23.79 +        io_apic_write(apic, address, val);
   23.80 +        ret = 0;
   23.81 +        break;
   23.82 +    case PHYSDEVOP_ASSIGN_VECTOR:
   23.83 +        if ( !IS_PRIV(current->domain) )
   23.84 +                return -EPERM;
   23.85 +        
   23.86 +        irq = op.u.irq_op.irq;
   23.87 +        op.u.irq_op.vector = assign_irq_vector(irq);
   23.88 +        ret = 0;
   23.89 +        break;
   23.90 +#endif
   23.91      case PHYSDEVOP_SET_IOPL:
   23.92          ret = -EINVAL;
   23.93          if ( op.u.set_iopl.iopl > 3 )
   23.94 @@ -716,7 +756,6 @@ long do_physdev_op(physdev_op_t *uop)
   23.95          current->arch.iobmp       = (u8 *)op.u.set_iobitmap.bitmap;
   23.96          current->arch.iobmp_limit = op.u.set_iobitmap.nr_ports;
   23.97          break;
   23.98 -
   23.99      default:
  23.100          ret = -EINVAL;
  23.101          break;
    24.1 --- a/xen/drivers/Makefile	Tue May 03 12:28:27 2005 +0000
    24.2 +++ b/xen/drivers/Makefile	Tue May 03 14:27:54 2005 +0000
    24.3 @@ -2,9 +2,9 @@
    24.4  default:
    24.5  	$(MAKE) -C char
    24.6  	$(MAKE) -C acpi
    24.7 -	$(MAKE) -C pci
    24.8 +	#$(MAKE) -C pci
    24.9  
   24.10  clean:
   24.11  	$(MAKE) -C char clean
   24.12  	$(MAKE) -C acpi clean
   24.13 -	$(MAKE) -C pci clean
   24.14 +	#$(MAKE) -C pci clean
    25.1 --- a/xen/include/asm-x86/config.h	Tue May 03 12:28:27 2005 +0000
    25.2 +++ b/xen/include/asm-x86/config.h	Tue May 03 14:27:54 2005 +0000
    25.3 @@ -23,10 +23,10 @@
    25.4  #define CONFIG_ACPI 1
    25.5  #define CONFIG_ACPI_BOOT 1
    25.6  
    25.7 -#define CONFIG_PCI 1
    25.8 -#define CONFIG_PCI_DIRECT 1
    25.9 +//#define CONFIG_PCI 0
   25.10 +//#define CONFIG_PCI_DIRECT 0
   25.11  #if defined(__i386__)
   25.12 -#define CONFIG_PCI_BIOS 1
   25.13 +//#define CONFIG_PCI_BIOS 0
   25.14  #endif
   25.15  
   25.16  #define CONFIG_IDE 1
   25.17 @@ -315,4 +315,6 @@ extern unsigned long xenheap_phys_end; /
   25.18  #define ELFSIZE 32
   25.19  #endif
   25.20  
   25.21 +#define __ARCH_HAS_IOAPIC
   25.22 +
   25.23  #endif /* __X86_CONFIG_H__ */
    26.1 --- a/xen/include/asm-x86/io_apic.h	Tue May 03 12:28:27 2005 +0000
    26.2 +++ b/xen/include/asm-x86/io_apic.h	Tue May 03 14:27:54 2005 +0000
    26.3 @@ -157,6 +157,8 @@ static inline int ioapic_setup_disabled(
    26.4  	return skip_ioapic_setup;
    26.5  }
    26.6  
    26.7 +extern int assign_irq_vector(int irq);
    26.8 +
    26.9  #else	/* !CONFIG_X86_IO_APIC */
   26.10  #define io_apic_assign_pci_irqs 0
   26.11  
    27.1 --- a/xen/include/public/physdev.h	Tue May 03 12:28:27 2005 +0000
    27.2 +++ b/xen/include/public/physdev.h	Tue May 03 14:27:54 2005 +0000
    27.3 @@ -17,6 +17,9 @@
    27.4  #define PHYSDEVOP_IRQ_STATUS_QUERY      5
    27.5  #define PHYSDEVOP_SET_IOPL              6
    27.6  #define PHYSDEVOP_SET_IOBITMAP          7
    27.7 +#define PHYSDEVOP_APIC_READ             8
    27.8 +#define PHYSDEVOP_APIC_WRITE            9
    27.9 +#define PHYSDEVOP_ASSIGN_VECTOR         10
   27.10  
   27.11  /* Read from PCI configuration space. */
   27.12  typedef struct {
   27.13 @@ -77,18 +80,37 @@ typedef struct {
   27.14      u32      __pad0;                  /* 12 */
   27.15  } PACKED physdevop_set_iobitmap_t; /* 16 bytes */
   27.16  
   27.17 +typedef struct {
   27.18 +    /* IN */
   27.19 +    u32 apic;                          /*  0 */
   27.20 +    u32 offset;
   27.21 +    /* IN or OUT */
   27.22 +    u64 value;
   27.23 +} PACKED physdevop_apic_t; 
   27.24 +
   27.25 +typedef struct {
   27.26 +    /* IN */
   27.27 +    u32 irq;                          /*  0 */
   27.28 +    /* OUT */
   27.29 +    u32 vector;
   27.30 +} PACKED physdevop_irq_t; 
   27.31 +
   27.32  typedef struct _physdev_op_st 
   27.33  {
   27.34      u32 cmd;                          /*  0 */
   27.35      u32 __pad;                        /*  4 */
   27.36      union {                           /*  8 */
   27.37 +#ifdef CONFIG_PCI
   27.38          physdevop_pci_cfgreg_read_t       pci_cfgreg_read;
   27.39          physdevop_pci_cfgreg_write_t      pci_cfgreg_write;
   27.40          physdevop_pci_initialise_device_t pci_initialise_device;
   27.41          physdevop_pci_probe_root_buses_t  pci_probe_root_buses;
   27.42 +#endif
   27.43          physdevop_irq_status_query_t      irq_status_query;
   27.44          physdevop_set_iopl_t              set_iopl;
   27.45          physdevop_set_iobitmap_t          set_iobitmap;
   27.46 +        physdevop_apic_t                  apic_op;
   27.47 +        physdevop_irq_t                   irq_op;
   27.48          u8                                __dummy[32];
   27.49      } PACKED u;
   27.50  } PACKED physdev_op_t; /* 40 bytes */