diff -r 413b6ca4bd5e xen/arch/x86/hvm/svm/amd_iommu/Makefile --- a/xen/arch/x86/hvm/svm/amd_iommu/Makefile Fri Nov 30 15:32:58 2007 +0100 +++ b/xen/arch/x86/hvm/svm/amd_iommu/Makefile Fri Nov 30 15:33:17 2007 +0100 @@ -2,3 +2,4 @@ obj-y += amd-iommu-init.o obj-y += amd-iommu-init.o obj-y += amd-iommu-map.o obj-y += pci-amd-iommu.o +obj-y += ht1100.o diff -r 413b6ca4bd5e xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c --- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c Fri Nov 30 15:32:58 2007 +0100 +++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c Fri Nov 30 15:33:17 2007 +0100 @@ -224,6 +224,10 @@ int __init scan_for_iommu(iommu_detect_c { int bus, dev, error = 0; +#if ENABLE_HT1100 + ht1100_fixup(); +#endif + for ( bus = 0; bus < PCI_MAX_BUS_COUNT && !error; ++bus ) { for ( dev = 0; dev < PCI_MAX_DEV_COUNT && !error; ++dev ) diff -r 413b6ca4bd5e xen/include/asm-x86/hvm/svm/amd-iommu-proto.h --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Fri Nov 30 15:32:58 2007 +0100 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Fri Nov 30 15:33:17 2007 +0100 @@ -80,6 +80,10 @@ void flush_command_buffer(struct amd_iom /* find iommu for bdf */ struct amd_iommu *find_iommu_for_device(int bus, int devfn); +#if ENABLE_HT1100 +void __init ht1100_fixup(void); +#endif + static inline u32 get_field_from_reg_u32(u32 reg_value, u32 mask, u32 shift) { u32 field; diff -r 413b6ca4bd5e xen/arch/x86/hvm/svm/amd_iommu/ht1100.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/hvm/svm/amd_iommu/ht1100.c Fri Nov 30 15:33:17 2007 +0100 @@ -0,0 +1,167 @@ +#include +#include +#include "pci-direct.h" +#include "pci_regs.h" + +#if ENABLE_HT1100 + +static void __init wait_a_little_bit(void) +{ + u32 wait, i; + + for (i=0; i < 999999; ++i) { + wait = 0x80000000; + do { + wait >>= 1; + } while(wait); + } +} + +static int __init ht1100_write_enable(int bus, int dev, int func) +{ + u32 retry, value, enable; + + value = read_pci_config(bus, dev, func, 0xFC); + value |= 0x02000000; + + retry = 99; + do { + write_pci_config(bus, dev, func, 0xFC, value); + wait_a_little_bit(); + enable = read_pci_config(bus, dev, func, 0xFC); + wait_a_little_bit(); + } while((enable & 0x02000000) == 0 && retry--); + + return (enable & 0x02000000) ? 0 : - ENODEV; +} + +static int __init ht1100_write_disable(int bus, int dev, int func) +{ + u32 retry, value, enable; + + value = read_pci_config(bus, dev, func, 0xFC); + value &= 0xFDFFFFFF; + + retry = 99; + do { + write_pci_config(bus, dev, func, 0xFC, value); + wait_a_little_bit(); + enable = read_pci_config(bus, dev, func, 0xFC); + wait_a_little_bit(); + } while((enable & 0x02000000) && retry--); + + return ((enable & 0x02000000) == 0) ? 0 : - ENODEV; +} + +static int __init ht1100_iommu_enable(int bus, int dev, int func) +{ + u32 retry, value, enable; + + value = read_pci_config(bus, dev, func, 0x0C); + value |= 0x00800000; + + retry = 99; + do { + write_pci_config(bus, dev, func, 0x0C, value); + wait_a_little_bit(); + enable = read_pci_config(bus, dev, func, 0x0C); + wait_a_little_bit(); + } while((enable & 0x00800000) == 0 && retry--); + + return (enable & 0x00800000) ? 0 : -ENODEV; +} + +void __init ht1100_fixup(void) +{ +#if HACK_BIOS_SETTINGS + /* set "Write-Enable" bit */ + ht1100_write_enable(0, 1, 0); + ht1100_write_enable(0, 2, 0); + ht1100_write_enable(0, 3, 0); + + /* enable IOMMU functions */ + ht1100_iommu_enable(0, 1, 0); + ht1100_iommu_enable(0, 2, 0); + ht1100_iommu_enable(0, 3, 0); + ht1100_iommu_enable(0, 4, 0); + ht1100_iommu_enable(0, 5, 0); + + /* fix-up "Last/First Device" range on IOMMU */ + write_pci_config(0, 1, 1, 0x5C, + read_pci_config(0, 1, 1, 0x5C) + 0x48080000); + write_pci_config(0, 2, 1, 0x5C, + read_pci_config(0, 2, 1, 0x5C) + 0x08080000); + write_pci_config(0, 3, 1, 0x5C, + read_pci_config(0, 3, 1, 0x5C) + 0x08080000); + write_pci_config(0, 4, 1, 0x5C, + read_pci_config(0, 4, 1, 0x5C) + 0x08080000); + write_pci_config(0, 5, 1, 0x5C, + read_pci_config(0, 5, 1, 0x5C) + 0x08080000); + + /* clear "Write-Enable" bit */ + ht1100_write_disable(0, 1, 0); + ht1100_write_disable(0, 2, 0); + ht1100_write_disable(0, 3, 0); + + /* enable MMIO access on IOMMU */ + write_pci_config(0, 1, 1, 0x04, + read_pci_config(0, 1, 1, 0x04) | 0x42); + write_pci_config(0, 2, 1, 0x04, + read_pci_config(0, 2, 1, 0x04) | 0x42); + write_pci_config(0, 3, 1, 0x04, + read_pci_config(0, 3, 1, 0x04) | 0x42); + write_pci_config(0, 4, 1, 0x04, + read_pci_config(0, 4, 1, 0x04) | 0x42); + write_pci_config(0, 5, 1, 0x04, + read_pci_config(0, 5, 1, 0x04) | 0x42); + + /* set MMIO base/limit at CPU0 */ + write_pci_config(0, 24, 1, 0x94, 0x00F10000); + +#if HACK_MMIO_ON_CPU1 + /* set MMIO base/limit at CPU1 */ + /* Don said: node1 is orthogonal to node0 */ + write_pci_config(0, 25, 1, 0x94, 0x00F10000); +#endif +#endif + +#if HACK_ISOC_SETTINGS + /* configure ISOC channel at IOMMU */ + write_pci_config(0, 1, 0, 0xB4, + read_pci_config(0, 1, 0, 0xB4) | 0x1000); + + /* configure ISOC channel at CPU0 */ + write_pci_config(0, 24, 0, 0x90, 0x8885026B); + write_pci_config(0, 24, 0, 0x94, 0x000F0000); + + /* clear DispRefModeEn */ + write_pci_config(0, 24, 0, 0x68, + read_pci_config(0, 24, 0, 0x68) & 0xFEFFFFFF); + + /* set IsocEn */ + write_pci_config(0, 24, 0, 0x84, + read_pci_config(0, 24, 0, 0x84) | 0x1000); + +#if HACK_ISOC_ON_CPU1 + /* configure ISOC channel at CPU1 */ + write_pci_config(0, 25, 0, 0x90, 0x8885026B); + write_pci_config(0, 25, 0, 0x94, 0x000F0000); + + /* clear DispRefModeEn */ + write_pci_config(0, 25, 0, 0x68, + read_pci_config(0, 25, 0, 0x68) & 0xFEFFFFFF); + + /* set IsocEn */ + write_pci_config(0, 25, 0, 0x84, + read_pci_config(0, 25, 0, 0x84) | 0x1000); +#endif +#endif + +#if HACK_BIOS_SETTINGS + /* enable PS/2 floppy */ + write_pci_config(0, 1, 0, 0x78, + read_pci_config(0, 1, 0, 0x78) & 0xFFFF00FF); +#endif +} + +#endif