WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [HVM] Reworked interrupt distribution log

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM] Reworked interrupt distribution logic.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 22 Nov 2006 11:10:13 +0000
Delivery-date: Wed, 22 Nov 2006 03:10:02 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID f555a90bcc373a7379bc18f875eac5e7c7122ae9
# Parent  b80f00215bbaf2050765e557f1a017a71e1e8529
[HVM] Reworked interrupt distribution logic.

TODO:
 1. Fix IO-APIC ID to not conflict with LAPIC IDS.
 2. Fix i8259 device model (seems to work already though!).
 3. Add INTSRC overrides in MPBIOS and ACPI tables so
    that PCI legacy IRQ routing always ends up at an
    IO-APIC input with level trigger. Restricting link
    routing to {5,6,10,11} and setting overrides for all
    four of those would work.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/firmware/hvmloader/acpi/acpi2_0.h  |    1 
 tools/firmware/hvmloader/acpi/dsdt.asl   |  608 ++++++++++++++++++------------
 tools/firmware/hvmloader/acpi/dsdt.c     |  621 +++++++++++++++++++------------
 tools/firmware/hvmloader/acpi/gen.c      |    2 
 tools/firmware/hvmloader/hvmloader.c     |    2 
 tools/firmware/hvmloader/mp_tables.c     |  484 +++++++++++-------------
 tools/firmware/rombios/rombios.c         |   92 ++--
 tools/ioemu/Makefile.target              |    6 
 tools/ioemu/target-i386-dm/i8259-dm.c    |    2 
 tools/ioemu/target-i386-dm/piix_pci-dm.c |  397 +++++++++++++++++++
 tools/libxc/xc_misc.c                    |   76 +++
 tools/libxc/xenctrl.h                    |   12 
 xen/arch/x86/hvm/Makefile                |    5 
 xen/arch/x86/hvm/hvm.c                   |  174 ++++++--
 xen/arch/x86/hvm/i8259.c                 |  111 +----
 xen/arch/x86/hvm/irq.c                   |  227 +++++++++++
 xen/arch/x86/hvm/rtc.c                   |  276 +++++++------
 xen/arch/x86/hvm/svm/intr.c              |   15 
 xen/arch/x86/hvm/vioapic.c               |  313 +++++----------
 xen/arch/x86/hvm/vlapic.c                |   11 
 xen/arch/x86/hvm/vmx/io.c                |   16 
 xen/include/asm-x86/hvm/domain.h         |   11 
 xen/include/asm-x86/hvm/io.h             |    1 
 xen/include/asm-x86/hvm/irq.h            |  107 +++++
 xen/include/asm-x86/hvm/vioapic.h        |   20 
 xen/include/asm-x86/hvm/vpic.h           |   18 
 xen/include/public/hvm/hvm_op.h          |   50 +-
 27 files changed, 2376 insertions(+), 1282 deletions(-)

diff -r b80f00215bba -r f555a90bcc37 tools/firmware/hvmloader/acpi/acpi2_0.h
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h   Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h   Tue Nov 21 19:22:25 2006 +0000
@@ -327,7 +327,6 @@ struct acpi_20_madt {
 #pragma pack ()
 
 #define ACPI_PHYSICAL_ADDRESS 0xEA000
-#define ACPI_TABLE_SIZE (4*1024)
 
 void AcpiBuildTable(uint8_t *buf);
 
diff -r b80f00215bba -r f555a90bcc37 tools/firmware/hvmloader/acpi/dsdt.asl
--- a/tools/firmware/hvmloader/acpi/dsdt.asl    Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/hvmloader/acpi/dsdt.asl    Tue Nov 21 19:22:25 2006 +0000
@@ -1,24 +1,21 @@
-//**********************************************************************//
-//*
-//* Copyright (c) 2004, Intel Corporation.
-//*
-//* This program is free software; you can redistribute it and/or modify it
-//* under the terms and conditions of the GNU General Public License,
-//* version 2, as published by the Free Software Foundation.
-//*
-//* This program is distributed in the hope it will be useful, but WITHOUT
-//* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-//* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-//* more details.
-//*
-//* You should have received a copy of the GNU General Public License along 
with
-//* this program; if not, write to the Free Software Foundation, Inc., 59 
Temple
-//* Place - Suite 330, Boston, MA 02111-1307 USA.
-
-//**
-//**  DSDT for Xen with Qemu device model
-//**
-//**
+/******************************************************************************
+ * DSDT for Xen with Qemu device model
+ *
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
 
 DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
 {
@@ -36,11 +33,9 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, 
         Processor (CPU1, 0x01, 0x00000000, 0x00) {}
         Processor (CPU2, 0x02, 0x00000000, 0x00) {}
         Processor (CPU3, 0x03, 0x00000000, 0x00) {}
-
     }
 
-/* Poweroff support - ties in with qemu emulation */
-
+    /* Poweroff support - ties in with qemu emulation */
     Name (\_S5, Package (0x04)
     {
         0x07,
@@ -49,318 +44,476 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, 
         0x00
     })
 
-
     Name(PICD, 0)
-
-    Method(_PIC, 1) { 
- 
-    Store(Arg0, PICD) 
+    Method(_PIC, 1)
+    {
+        Store(Arg0, PICD) 
     }
+
     Scope (\_SB)
     {
-       /* Fix HCT test for 0x400 pci memory - need to report low 640 MB mem as 
motherboard resource            */
-
-       Device(MEM0) {
+        /* Fix HCT test for 0x400 pci memory:
+         * - need to report low 640 MB mem as motherboard resource
+         */
+
+       Device(MEM0)
+       {
            Name(_HID, EISAID("PNP0C02"))
            Name(_CRS, ResourceTemplate() {
-           QWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, 
Cacheable, ReadWrite,
+               QWordMemory(
+                    ResourceConsumer, PosDecode, MinFixed,
+                    MaxFixed, Cacheable, ReadWrite,
                     0x00000000,
                     0x00000000,
                     0x0009ffff,
                     0x00000000,
                     0x000a0000)
-           }
-           )
+           })
        }
 
        Device (PCI0)
-        {
+       {
            Name (_HID, EisaId ("PNP0A03"))
            Name (_UID, 0x00)
            Name (_ADR, 0x00)
            Name (_BBN, 0x00)
            OperationRegion (PIRP, PCI_Config, 0x3c, 0x10)
            Field(PIRP, ByteAcc, NoLock, Preserve){        
-          IRQ3,3,
-          IRQ5,5,
-          IRQ7,7,
-          IRQ9,9,
-          IRQA,10,
-          IRQB,11
-         }
+               IRQ3, 3,
+               IRQ5, 5,
+               IRQ7, 7,
+               IRQ9, 9,
+               IRQA, 10,
+               IRQB, 11
+           }
  
-            Method (_CRS, 0, NotSerialized)
-            {
-          
+           Method (_CRS, 0, NotSerialized)
+           {
                Name (PRT0, ResourceTemplate ()
-                {
-         /* bus number is from 0 - 255*/
-                    WordBusNumber (ResourceConsumer, MinFixed, MaxFixed, 
SubDecode,
+               {
+                   /* bus number is from 0 - 255*/
+                   WordBusNumber(
+                        ResourceConsumer, MinFixed, MaxFixed, SubDecode,
                         0x0000,
                         0x0000,
                         0x00FF,
                         0x0000,
                         0x0100)
                     IO (Decode16, 0x0CF8, 0x0CF8, 0x01, 0x08)
-                    WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, 
EntireRange,
+                    WordIO(
+                        ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                        EntireRange,
                         0x0000,
                         0x0000,
                         0x0CF7,
                         0x0000,
                         0x0CF8)
-                    WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, 
EntireRange,
+                    WordIO(
+                        ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                        EntireRange,
                         0x0000,
                         0x0D00,
                         0xFFFF,
                         0x0000,
                         0xF300)
 
-                /* reserve memory for pci devices */
-
-                    DWordMemory (ResourceProducer, PosDecode, MinFixed, 
MaxFixed, Cacheable, ReadWrite,
+                    /* reserve memory for pci devices */
+                    DWordMemory(
+                        ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                        Cacheable, ReadWrite,
                         0x00000000,
                         0x000A0000,
                         0x000BFFFF,
                         0x00000000,
                         0x00020000)
 
-                    DWordMemory (ResourceConsumer, PosDecode, MinFixed, 
MaxFixed, Cacheable, ReadWrite,
+                    DWordMemory(
+                        ResourceConsumer, PosDecode, MinFixed, MaxFixed,
+                        Cacheable, ReadWrite,
                         0x00000000,
                         0xF0000000,
                         0xF4FFFFFF,
                         0x00000000,
                         0x05000000)
-
                 })
                 Return (PRT0)
             }
-       Name(BUFA, ResourceTemplate() {
+
+            Name(BUFA, ResourceTemplate() {
                 IRQ(Level, ActiveLow, Shared) {
-                        3,4,5,6,7,10,11,12,14,15} 
-                }) 
-
-                Name(BUFB, Buffer(){
-                0x23, 0x00, 0x00, 0x18,
-                0x79, 0})
-
-                CreateWordField(BUFB, 0x01, IRQV)
-
-                Name(BUFC, Buffer(){
-                5, 7, 10, 11
-                 })
-                
-                CreateByteField(BUFC, 0x01, PIQA)
-                CreateByteField(BUFC, 0x01, PIQB)
-                CreateByteField(BUFC, 0x01, PIQC)
-                CreateByteField(BUFC, 0x01, PIQD)
-                
-                Device(LNKA)    {
-                Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
+                    3,4,5,6,7,10,11,12,14,15
+                }
+            })
+
+            Name(BUFB, Buffer() {
+                0x23, 0x00, 0x00, 0x18, 0x79, 0
+            })
+
+            CreateWordField(BUFB, 0x01, IRQV)
+
+            Device(LNKA) {
+                Name(_HID, EISAID("PNP0C0F")) /* PCI interrupt link */
                 Name(_UID, 1)
+
                 Method(_STA, 0) {
-                               And(PIRA, 0x80, Local0)
-                        If(LEqual(Local0, 0x80)) {
-                                Return(0x09)   
-                                }
-                        Else {
-                                Return(0x0B) 
-                                }
-                        }
+                    And(PIRA, 0x80, Local0)
+                    If(LEqual(Local0, 0x80)) {
+                        Return(0x09)   
+                    } Else {
+                        Return(0x0B) 
+                    }
+                }
 
                 Method(_PRS) {
-
-                        Return(BUFA)
-                } // Method(_PRS)
+                    Return(BUFA)
+                }
 
                 Method(_DIS) {
-                               Or(PIRA, 0x80, PIRA)
+                    Or(PIRA, 0x80, PIRA)
                 }
 
                 Method(_CRS) {
-                        And(PIRB, 0x0f, Local0) 
-                        ShiftLeft(0x1, Local0, IRQV) 
-                        Return(BUFB) 
-                } 
+                    And(PIRA, 0x0f, Local0)
+                    ShiftLeft(0x1, Local0, IRQV)
+                    Return(BUFB)
+                }
 
                 Method(_SRS, 1) {
-                                CreateWordField(ARG0, 0x01, IRQ1) 
-                        FindSetRightBit(IRQ1, Local0) 
-                        Decrement(Local0) 
-                        Store(Local0, PIRA)
-                 } // Method(_SRS)
-        }
-
-        Device(LNKB){
-                Name(_HID, EISAID("PNP0C0F"))  
+                    CreateWordField(ARG0, 0x01, IRQ1)
+                    FindSetRightBit(IRQ1, Local0)
+                    Decrement(Local0)
+                    Store(Local0, PIRA)
+                }
+            }
+
+            Device(LNKB) {
+                Name(_HID, EISAID("PNP0C0F")) /* PCI interrupt link */
                 Name(_UID, 2)
+
                 Method(_STA, 0) {
-                               And(PIRB, 0x80, Local0)
-                        If(LEqual(Local0, 0x80)) {
-                                Return(0x09) 
-                                }
-                        Else {
-                                Return(0x0B) 
-                                }
-                        }
+                    And(PIRB, 0x80, Local0)
+                    If(LEqual(Local0, 0x80)) {
+                        Return(0x09) 
+                    } Else {
+                        Return(0x0B) 
+                    }
+                }
 
                 Method(_PRS) {
-                                Return(BUFA) 
-                } // Method(_PRS)
+                    Return(BUFA) 
+                }
 
                 Method(_DIS) {
-
-                               Or(PIRB, 0x80, PIRB)
+                    Or(PIRB, 0x80, PIRB)
                 }
 
                 Method(_CRS) {
-                        And(PIRB, 0x0f, Local0) 
-                        ShiftLeft(0x1, Local0, IRQV) 
-                        Return(BUFB) 
-                } // Method(_CRS)
+                    And(PIRB, 0x0f, Local0) 
+                    ShiftLeft(0x1, Local0, IRQV) 
+                    Return(BUFB) 
+                }
 
                 Method(_SRS, 1) {
-                        CreateWordField(ARG0, 0x01, IRQ1) 
-                        FindSetRightBit(IRQ1, Local0) 
-                        Decrement(Local0)
-                        Store(Local0, PIRB) 
-                 } // Method(_SRS)
-        }
-
-        Device(LNKC){
-                Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
+                    CreateWordField(ARG0, 0x01, IRQ1) 
+                    FindSetRightBit(IRQ1, Local0) 
+                    Decrement(Local0)
+                    Store(Local0, PIRB) 
+                }
+            }
+
+            Device(LNKC) {
+                Name(_HID, EISAID("PNP0C0F")) /* PCI interrupt link */
                 Name(_UID, 3)
+
                 Method(_STA, 0) {
-                        And(PIRC, 0x80, Local0)
-                        If(LEqual(Local0, 0x80)) {
-                                Return(0x09) 
-                        }
-                        Else {
-                                Return(0x0B)
-                        }
+                    And(PIRC, 0x80, Local0)
+                    If(LEqual(Local0, 0x80)) {
+                        Return(0x09) 
+                    } Else {
+                        Return(0x0B)
+                    }
                 }
 
                 Method(_PRS) { 
-                        Return(BUFA)
-                } // Method(_PRS)
+                    Return(BUFA)
+                }
 
                 Method(_DIS) {
-
-                               Or(PIRC, 0x80, PIRC)
+                    Or(PIRC, 0x80, PIRC)
                 }
 
                 Method(_CRS) {
-                        And(PIRC, 0x0f, Local0) 
-                        ShiftLeft(0x1, Local0, IRQV) 
-                        Return(BUFB) 
-                } // Method(_CRS)
+                    And(PIRC, 0x0f, Local0) 
+                    ShiftLeft(0x1, Local0, IRQV) 
+                    Return(BUFB) 
+                }
 
                 Method(_SRS, 1) {
-                                CreateWordField(ARG0, 0x01, IRQ1) 
-                        FindSetRightBit(IRQ1, Local0) 
-                        Decrement(Local0) 
-                        Store(Local0, PIRC)
-                 } // Method(_SRS)
-        }
-
-        Device(LNKD) {
-                Name(_HID, EISAID("PNP0C0F"))  
+                    CreateWordField(ARG0, 0x01, IRQ1) 
+                    FindSetRightBit(IRQ1, Local0) 
+                    Decrement(Local0) 
+                    Store(Local0, PIRC)
+                }
+            }
+
+            Device(LNKD) {
+                Name(_HID, EISAID("PNP0C0F")) /* PCI interrupt link */
                 Name(_UID, 4)
+
                 Method(_STA, 0) {
-                               And(PIRD, 0x80, Local0)
-                        If(LEqual(Local0, 0x80)) {
-                                Return(0x09) 
-                        }
-                        Else {
-                                Return(0x0B) 
-                        }
+                    And(PIRD, 0x80, Local0)
+                    If(LEqual(Local0, 0x80)) {
+                        Return(0x09) 
+                    } Else {
+                        Return(0x0B) 
+                    }
                 }
 
                 Method(_PRS) { 
-                        Return(BUFA) 
-                } // Method(_PRS)
+                    Return(BUFA) 
+                }
 
                 Method(_DIS) {
-                               Or(PIRD, 0x80, PIRD)
+                    Or(PIRD, 0x80, PIRD)
                 }
 
                 Method(_CRS) {
-                        And(PIRD, 0x0f, Local0) 
-                        ShiftLeft(0x1, Local0, IRQV) 
-                        Return(BUFB) 
-                } // Method(_CRS)
+                    And(PIRD, 0x0f, Local0) 
+                    ShiftLeft(0x1, Local0, IRQV) 
+                    Return(BUFB) 
+                }
 
                 Method(_SRS, 1) {
-                                CreateWordField(ARG0, 0x01, IRQ1) 
-                        FindSetRightBit(IRQ1, Local0) 
-                        Decrement(Local0) 
-                        Store(Local0, PIRD) 
-                 } // Method(_SRS)
-        }
-        Method(_PRT,0) {
-               If(PICD) {Return(PRTA)}  
-               Return (PRTP)  
-               } // end _PRT
-
-        Name(PRTP, Package() {
-                        // Slot 1, INTA - INTD
-                        Package(){0x0000ffff, 0, \_SB.PCI0.LNKA, 0},
-                        Package(){0x0000ffff, 1, \_SB.PCI0.LNKB, 0},
-                        Package(){0x0000ffff, 2, \_SB.PCI0.LNKC, 0},
-                        Package(){0x0000ffff, 3, \_SB.PCI0.LNKD, 0},
-
-                        // Slot 2, INTA - INTD
-                        Package(){0x0001ffff, 0, \_SB.PCI0.LNKB, 0},
-                        Package(){0x0001ffff, 1, \_SB.PCI0.LNKC, 0},
-                        Package(){0x0001ffff, 2, \_SB.PCI0.LNKD, 0},
-                        Package(){0x0001ffff, 3, \_SB.PCI0.LNKA, 0},
-                        
-                        // Slot 3, INTA - INTD
-                        Package(){0x0002ffff, 0, \_SB.PCI0.LNKC, 0},
-                        Package(){0x0002ffff, 1, \_SB.PCI0.LNKD, 0},
-                        Package(){0x0002ffff, 2, \_SB.PCI0.LNKA, 0},
-                        Package(){0x0002ffff, 3, \_SB.PCI0.LNKB, 0},
-                        
-                        // Slot 4, INTA - INTD
-                        Package(){0x0003ffff, 0, \_SB.PCI0.LNKD, 0},
-                        Package(){0x0003ffff, 1, \_SB.PCI0.LNKA, 0},
-                        Package(){0x0003ffff, 2, \_SB.PCI0.LNKB, 0},
-                        Package(){0x0003ffff, 3, \_SB.PCI0.LNKC, 0},
-                        
-                        // Slot 5, INTA - INTD
-                        Package(){0x0004ffff, 0, \_SB.PCI0.LNKA, 0},
-                        Package(){0x0004ffff, 1, \_SB.PCI0.LNKB, 0},
-                        Package(){0x0004ffff, 2, \_SB.PCI0.LNKC, 0},
-                        Package(){0x0004ffff, 3, \_SB.PCI0.LNKD, 0},
-                        }
-            )
-        Name(PRTA, Package(){
-                        Package(){0x0001ffff, 0, 0, 5},  // Device 1, INTA
-                        Package(){0x0002ffff, 0, 0, 7},  // Device 2, INTA
-                        Package(){0x0003ffff, 0, 0, 10}, // Device 3, INTA
-                        Package(){0x0004ffff, 0, 0, 11}, // Device 4, INTA
-                        }
-            )
+                    CreateWordField(ARG0, 0x01, IRQ1) 
+                    FindSetRightBit(IRQ1, Local0) 
+                    Decrement(Local0) 
+                    Store(Local0, PIRD) 
+                }
+            }
+
+            Method(_PRT,0) {
+                If(PICD) {
+                    Return(PRTA)
+                }  
+                Return (PRTP)  
+            }
+
+            Name(PRTP, Package() {
+                /* Device 0, INTA - INTD */
+                Package(){0x0000ffff, 0, \_SB.PCI0.LNKA, 0},
+                Package(){0x0000ffff, 1, \_SB.PCI0.LNKB, 0},
+                Package(){0x0000ffff, 2, \_SB.PCI0.LNKC, 0},
+                Package(){0x0000ffff, 3, \_SB.PCI0.LNKD, 0},
+
+                /* Device 1, INTA - INTD */
+                Package(){0x0001ffff, 0, \_SB.PCI0.LNKB, 0},
+                Package(){0x0001ffff, 1, \_SB.PCI0.LNKC, 0},
+                Package(){0x0001ffff, 2, \_SB.PCI0.LNKD, 0},
+                Package(){0x0001ffff, 3, \_SB.PCI0.LNKA, 0},
+                        
+                /* Device 2, INTA - INTD */
+                Package(){0x0002ffff, 0, \_SB.PCI0.LNKC, 0},
+                Package(){0x0002ffff, 1, \_SB.PCI0.LNKD, 0},
+                Package(){0x0002ffff, 2, \_SB.PCI0.LNKA, 0},
+                Package(){0x0002ffff, 3, \_SB.PCI0.LNKB, 0},
+                        
+                /* Device 3, INTA - INTD */
+                Package(){0x0003ffff, 0, \_SB.PCI0.LNKD, 0},
+                Package(){0x0003ffff, 1, \_SB.PCI0.LNKA, 0},
+                Package(){0x0003ffff, 2, \_SB.PCI0.LNKB, 0},
+                Package(){0x0003ffff, 3, \_SB.PCI0.LNKC, 0},
+                        
+                /* Device 4, INTA - INTD */
+                Package(){0x0004ffff, 0, \_SB.PCI0.LNKA, 0},
+                Package(){0x0004ffff, 1, \_SB.PCI0.LNKB, 0},
+                Package(){0x0004ffff, 2, \_SB.PCI0.LNKC, 0},
+                Package(){0x0004ffff, 3, \_SB.PCI0.LNKD, 0},
+                        
+                /* Device 5, INTA - INTD */
+                Package(){0x0005ffff, 0, \_SB.PCI0.LNKB, 0},
+                Package(){0x0005ffff, 1, \_SB.PCI0.LNKC, 0},
+                Package(){0x0005ffff, 2, \_SB.PCI0.LNKD, 0},
+                Package(){0x0005ffff, 3, \_SB.PCI0.LNKA, 0},
+                        
+                /* Device 6, INTA - INTD */
+                Package(){0x0006ffff, 0, \_SB.PCI0.LNKC, 0},
+                Package(){0x0006ffff, 1, \_SB.PCI0.LNKD, 0},
+                Package(){0x0006ffff, 2, \_SB.PCI0.LNKA, 0},
+                Package(){0x0006ffff, 3, \_SB.PCI0.LNKB, 0},
+                        
+                /* Device 7, INTA - INTD */
+                Package(){0x0007ffff, 0, \_SB.PCI0.LNKD, 0},
+                Package(){0x0007ffff, 1, \_SB.PCI0.LNKA, 0},
+                Package(){0x0007ffff, 2, \_SB.PCI0.LNKB, 0},
+                Package(){0x0007ffff, 3, \_SB.PCI0.LNKC, 0},
+                        
+                /* Device 8, INTA - INTD */
+                Package(){0x0008ffff, 0, \_SB.PCI0.LNKA, 0},
+                Package(){0x0008ffff, 1, \_SB.PCI0.LNKB, 0},
+                Package(){0x0008ffff, 2, \_SB.PCI0.LNKC, 0},
+                Package(){0x0008ffff, 3, \_SB.PCI0.LNKD, 0},
+                        
+                /* Device 9, INTA - INTD */
+                Package(){0x0009ffff, 0, \_SB.PCI0.LNKB, 0},
+                Package(){0x0009ffff, 1, \_SB.PCI0.LNKC, 0},
+                Package(){0x0009ffff, 2, \_SB.PCI0.LNKD, 0},
+                Package(){0x0009ffff, 3, \_SB.PCI0.LNKA, 0},
+                        
+                /* Device 10, INTA - INTD */
+                Package(){0x000affff, 0, \_SB.PCI0.LNKC, 0},
+                Package(){0x000affff, 1, \_SB.PCI0.LNKD, 0},
+                Package(){0x000affff, 2, \_SB.PCI0.LNKA, 0},
+                Package(){0x000affff, 3, \_SB.PCI0.LNKB, 0},
+                        
+                /* Device 11, INTA - INTD */
+                Package(){0x000bffff, 0, \_SB.PCI0.LNKD, 0},
+                Package(){0x000bffff, 1, \_SB.PCI0.LNKA, 0},
+                Package(){0x000bffff, 2, \_SB.PCI0.LNKB, 0},
+                Package(){0x000bffff, 3, \_SB.PCI0.LNKC, 0},
+                        
+                /* Device 12, INTA - INTD */
+                Package(){0x000cffff, 0, \_SB.PCI0.LNKA, 0},
+                Package(){0x000cffff, 1, \_SB.PCI0.LNKB, 0},
+                Package(){0x000cffff, 2, \_SB.PCI0.LNKC, 0},
+                Package(){0x000cffff, 3, \_SB.PCI0.LNKD, 0},
+                        
+                /* Device 13, INTA - INTD */
+                Package(){0x000dffff, 0, \_SB.PCI0.LNKB, 0},
+                Package(){0x000dffff, 1, \_SB.PCI0.LNKC, 0},
+                Package(){0x000dffff, 2, \_SB.PCI0.LNKD, 0},
+                Package(){0x000dffff, 3, \_SB.PCI0.LNKA, 0},
+                        
+                /* Device 14, INTA - INTD */
+                Package(){0x000effff, 0, \_SB.PCI0.LNKC, 0},
+                Package(){0x000effff, 1, \_SB.PCI0.LNKD, 0},
+                Package(){0x000effff, 2, \_SB.PCI0.LNKA, 0},
+                Package(){0x000effff, 3, \_SB.PCI0.LNKB, 0},
+                        
+                /* Device 15, INTA - INTD */
+                Package(){0x000fffff, 0, \_SB.PCI0.LNKD, 0},
+                Package(){0x000fffff, 1, \_SB.PCI0.LNKA, 0},
+                Package(){0x000fffff, 2, \_SB.PCI0.LNKB, 0},
+                Package(){0x000fffff, 3, \_SB.PCI0.LNKC, 0},
+            })
+
+            Name(PRTA, Package() {
+                /* Device 0, INTA - INTD */
+                Package(){0x0000ffff, 0, 0, 16},
+                Package(){0x0000ffff, 1, 0, 17},
+                Package(){0x0000ffff, 2, 0, 18},
+                Package(){0x0000ffff, 3, 0, 19},
+
+                /* Device 1, INTA - INTD */
+                Package(){0x0001ffff, 0, 0, 20},
+                Package(){0x0001ffff, 1, 0, 21},
+                Package(){0x0001ffff, 2, 0, 22},
+                Package(){0x0001ffff, 3, 0, 23},
+
+                /* Device 2, INTA - INTD */
+                Package(){0x0002ffff, 0, 0, 24},
+                Package(){0x0002ffff, 1, 0, 25},
+                Package(){0x0002ffff, 2, 0, 26},
+                Package(){0x0002ffff, 3, 0, 27},
+
+                /* Device 3, INTA - INTD */
+                Package(){0x0003ffff, 0, 0, 28},
+                Package(){0x0003ffff, 1, 0, 29},
+                Package(){0x0003ffff, 2, 0, 30},
+                Package(){0x0003ffff, 3, 0, 31},
+
+                /* Device 4, INTA - INTD */
+                Package(){0x0004ffff, 0, 0, 32},
+                Package(){0x0004ffff, 1, 0, 33},
+                Package(){0x0004ffff, 2, 0, 34},
+                Package(){0x0004ffff, 3, 0, 35},
+
+                /* Device 5, INTA - INTD */
+                Package(){0x0005ffff, 0, 0, 36},
+                Package(){0x0005ffff, 1, 0, 37},
+                Package(){0x0005ffff, 2, 0, 38},
+                Package(){0x0005ffff, 3, 0, 39},
+
+                /* Device 6, INTA - INTD */
+                Package(){0x0006ffff, 0, 0, 40},
+                Package(){0x0006ffff, 1, 0, 41},
+                Package(){0x0006ffff, 2, 0, 42},
+                Package(){0x0006ffff, 3, 0, 43},
+
+                /* Device 7, INTA - INTD */
+                Package(){0x0007ffff, 0, 0, 44},
+                Package(){0x0007ffff, 1, 0, 45},
+                Package(){0x0007ffff, 2, 0, 46},
+                Package(){0x0007ffff, 3, 0, 47},
+
+                /* Device 8, INTA - INTD */
+                Package(){0x0008ffff, 0, 0, 17},
+                Package(){0x0008ffff, 1, 0, 18},
+                Package(){0x0008ffff, 2, 0, 19},
+                Package(){0x0008ffff, 3, 0, 20},
+
+                /* Device 9, INTA - INTD */
+                Package(){0x0009ffff, 0, 0, 21},
+                Package(){0x0009ffff, 1, 0, 22},
+                Package(){0x0009ffff, 2, 0, 23},
+                Package(){0x0009ffff, 3, 0, 24},
+
+                /* Device 10, INTA - INTD */
+                Package(){0x000affff, 0, 0, 25},
+                Package(){0x000affff, 1, 0, 26},
+                Package(){0x000affff, 2, 0, 27},
+                Package(){0x000affff, 3, 0, 28},
+
+                /* Device 11, INTA - INTD */
+                Package(){0x000bffff, 0, 0, 29},
+                Package(){0x000bffff, 1, 0, 30},
+                Package(){0x000bffff, 2, 0, 31},
+                Package(){0x000bffff, 3, 0, 32},
+
+                /* Device 12, INTA - INTD */
+                Package(){0x000cffff, 0, 0, 33},
+                Package(){0x000cffff, 1, 0, 34},
+                Package(){0x000cffff, 2, 0, 35},
+                Package(){0x000cffff, 3, 0, 36},
+
+                /* Device 13, INTA - INTD */
+                Package(){0x000dffff, 0, 0, 37},
+                Package(){0x000dffff, 1, 0, 38},
+                Package(){0x000dffff, 2, 0, 39},
+                Package(){0x000dffff, 3, 0, 40},
+
+                /* Device 14, INTA - INTD */
+                Package(){0x000effff, 0, 0, 41},
+                Package(){0x000effff, 1, 0, 42},
+                Package(){0x000effff, 2, 0, 43},
+                Package(){0x000effff, 3, 0, 44},
+
+                /* Device 15, INTA - INTD */
+                Package(){0x000fffff, 0, 0, 45},
+                Package(){0x000fffff, 1, 0, 46},
+                Package(){0x000fffff, 2, 0, 47},
+                Package(){0x000fffff, 3, 0, 16},
+            })
             
             Device (ISA)
             {
-                Name (_ADR, 0x00000000) /* device id, PCI bus num, ... */
- 
-            OperationRegion(PIRQ, PCI_Config, 0x60, 0x4)
-                        Scope(\) {
-                                 Field (\_SB.PCI0.ISA.PIRQ, ByteAcc, NoLock, 
Preserve) {
-                                        PIRA, 8,
-                                        PIRB, 8,
-                                        PIRC, 8,
-                                        PIRD, 8
-                                        }
-                                 }
+                Name (_ADR, 0x00010000) /* device 1, fn 0 */
+
+                OperationRegion(PIRQ, PCI_Config, 0x60, 0x4)
+                Scope(\) {
+                    Field (\_SB.PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
+                        PIRA, 8,
+                        PIRB, 8,
+                        PIRC, 8,
+                        PIRD, 8
+                    }
+                }
                 Device (SYSR)
                 {
                     Name (_HID, EisaId ("PNP0C02"))
                     Name (_UID, 0x01)
                     Name (CRS, ResourceTemplate ()
                     {
-               /* TODO: list hidden resources */
+                        /* TODO: list hidden resources */
                         IO (Decode16, 0x0010, 0x0010, 0x00, 0x10)
                         IO (Decode16, 0x0022, 0x0022, 0x00, 0x0C)
                         IO (Decode16, 0x0030, 0x0030, 0x00, 0x10)
@@ -525,4 +678,3 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, 
         }
     }
 }
-
diff -r b80f00215bba -r f555a90bcc37 tools/firmware/hvmloader/acpi/dsdt.c
--- a/tools/firmware/hvmloader/acpi/dsdt.c      Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/hvmloader/acpi/dsdt.c      Tue Nov 21 19:22:25 2006 +0000
@@ -5,15 +5,15 @@
  * Copyright (C) 2000 - 2005 Intel Corporation
  * Supports ACPI Specification Revision 3.0
  * 
- * Compilation of "dsdt.asl" - Fri Nov 17 10:00:20 2006
+ * Compilation of "dsdt.asl" - Tue Nov 21 17:20:04 2006
  * 
  * C source code output
  *
  */
 unsigned char AmlCode[] = 
 {
-    0x44,0x53,0x44,0x54,0xF4,0x08,0x00,0x00,  /* 00000000    "DSDT...." */
-    0x01,0x22,0x49,0x4E,0x54,0x45,0x4C,0x00,  /* 00000008    "."INTEL." */
+    0x44,0x53,0x44,0x54,0x2A,0x0E,0x00,0x00,  /* 00000000    "DSDT*..." */
+    0x01,0x18,0x49,0x4E,0x54,0x45,0x4C,0x00,  /* 00000008    "..INTEL." */
     0x69,0x6E,0x74,0x2D,0x78,0x65,0x6E,0x00,  /* 00000010    "int-xen." */
     0xD6,0x07,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
     0x13,0x05,0x05,0x20,0x08,0x50,0x4D,0x42,  /* 00000020    "... .PMB" */
@@ -34,7 +34,7 @@ unsigned char AmlCode[] =
     0x12,0x08,0x04,0x0A,0x07,0x0A,0x07,0x00,  /* 00000098    "........" */
     0x00,0x08,0x50,0x49,0x43,0x44,0x00,0x14,  /* 000000A0    "..PICD.." */
     0x0C,0x5F,0x50,0x49,0x43,0x01,0x70,0x68,  /* 000000A8    "._PIC.ph" */
-    0x50,0x49,0x43,0x44,0x10,0x4F,0x83,0x5F,  /* 000000B0    "PICD.O._" */
+    0x50,0x49,0x43,0x44,0x10,0x45,0xD7,0x5F,  /* 000000B0    "PICD.E._" */
     0x53,0x42,0x5F,0x5B,0x82,0x49,0x04,0x4D,  /* 000000B8    "SB_[.I.M" */
     0x45,0x4D,0x30,0x08,0x5F,0x48,0x49,0x44,  /* 000000C0    "EM0._HID" */
     0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F,0x43,  /* 000000C8    ".A...._C" */
@@ -45,7 +45,7 @@ unsigned char AmlCode[] =
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 000000F0    "........" */
     0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,  /* 000000F8    "........" */
     0x00,0x00,0x00,0x00,0x79,0x00,0x5B,0x82,  /* 00000100    "....y.[." */
-    0x4C,0x7E,0x50,0x43,0x49,0x30,0x08,0x5F,  /* 00000108    "L~PCI0._" */
+    0x42,0xD2,0x50,0x43,0x49,0x30,0x08,0x5F,  /* 00000108    "B.PCI0._" */
     0x48,0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03,  /* 00000110    "HID.A..." */
     0x08,0x5F,0x55,0x49,0x44,0x00,0x08,0x5F,  /* 00000118    "._UID.._" */
     0x41,0x44,0x52,0x00,0x08,0x5F,0x42,0x42,  /* 00000120    "ADR.._BB" */
@@ -77,227 +77,394 @@ unsigned char AmlCode[] =
     0x42,0x55,0x46,0x42,0x11,0x09,0x0A,0x06,  /* 000001F0    "BUFB...." */
     0x23,0x00,0x00,0x18,0x79,0x00,0x8B,0x42,  /* 000001F8    "#...y..B" */
     0x55,0x46,0x42,0x01,0x49,0x52,0x51,0x56,  /* 00000200    "UFB.IRQV" */
-    0x08,0x42,0x55,0x46,0x43,0x11,0x07,0x0A,  /* 00000208    ".BUFC..." */
-    0x04,0x05,0x07,0x0A,0x0B,0x8C,0x42,0x55,  /* 00000210    "......BU" */
-    0x46,0x43,0x01,0x50,0x49,0x51,0x41,0x8C,  /* 00000218    "FC.PIQA." */
-    0x42,0x55,0x46,0x43,0x01,0x50,0x49,0x51,  /* 00000220    "BUFC.PIQ" */
-    0x42,0x8C,0x42,0x55,0x46,0x43,0x01,0x50,  /* 00000228    "B.BUFC.P" */
-    0x49,0x51,0x43,0x8C,0x42,0x55,0x46,0x43,  /* 00000230    "IQC.BUFC" */
-    0x01,0x50,0x49,0x51,0x44,0x5B,0x82,0x48,  /* 00000238    ".PIQD[.H" */
-    0x08,0x4C,0x4E,0x4B,0x41,0x08,0x5F,0x48,  /* 00000240    ".LNKA._H" */
-    0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,  /* 00000248    "ID.A...." */
-    0x5F,0x55,0x49,0x44,0x01,0x14,0x1C,0x5F,  /* 00000250    "_UID..._" */
-    0x53,0x54,0x41,0x00,0x7B,0x50,0x49,0x52,  /* 00000258    "STA.{PIR" */
-    0x41,0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,  /* 00000260    "A..`...`" */
-    0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,  /* 00000268    "........" */
-    0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,  /* 00000270    "...._PRS" */
-    0x00,0xA4,0x42,0x55,0x46,0x41,0x14,0x11,  /* 00000278    "..BUFA.." */
-    0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x49,  /* 00000280    "_DIS.}PI" */
-    0x52,0x41,0x0A,0x80,0x50,0x49,0x52,0x41,  /* 00000288    "RA..PIRA" */
-    0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,  /* 00000290    ".._CRS.{" */
-    0x50,0x49,0x52,0x42,0x0A,0x0F,0x60,0x79,  /* 00000298    "PIRB..`y" */
-    0x01,0x60,0x49,0x52,0x51,0x56,0xA4,0x42,  /* 000002A0    ".`IRQV.B" */
-    0x55,0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,  /* 000002A8    "UFB.._SR" */
-    0x53,0x01,0x8B,0x68,0x01,0x49,0x52,0x51,  /* 000002B0    "S..h.IRQ" */
-    0x31,0x82,0x49,0x52,0x51,0x31,0x60,0x76,  /* 000002B8    "1.IRQ1`v" */
-    0x60,0x70,0x60,0x50,0x49,0x52,0x41,0x5B,  /* 000002C0    "`p`PIRA[" */
-    0x82,0x49,0x08,0x4C,0x4E,0x4B,0x42,0x08,  /* 000002C8    ".I.LNKB." */
-    0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,  /* 000002D0    "_HID.A.." */
-    0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,  /* 000002D8    ".._UID.." */
-    0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,  /* 000002E0    ".._STA.{" */
-    0x50,0x49,0x52,0x42,0x0A,0x80,0x60,0xA0,  /* 000002E8    "PIRB..`." */
-    0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,  /* 000002F0    "..`....." */
-    0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,  /* 000002F8    "......._" */
-    0x50,0x52,0x53,0x00,0xA4,0x42,0x55,0x46,  /* 00000300    "PRS..BUF" */
-    0x41,0x14,0x11,0x5F,0x44,0x49,0x53,0x00,  /* 00000308    "A.._DIS." */
-    0x7D,0x50,0x49,0x52,0x42,0x0A,0x80,0x50,  /* 00000310    "}PIRB..P" */
-    0x49,0x52,0x42,0x14,0x1A,0x5F,0x43,0x52,  /* 00000318    "IRB.._CR" */
-    0x53,0x00,0x7B,0x50,0x49,0x52,0x42,0x0A,  /* 00000320    "S.{PIRB." */
-    0x0F,0x60,0x79,0x01,0x60,0x49,0x52,0x51,  /* 00000328    ".`y.`IRQ" */
-    0x56,0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,  /* 00000330    "V.BUFB.." */
-    0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,0x01,  /* 00000338    "_SRS..h." */
-    0x49,0x52,0x51,0x31,0x82,0x49,0x52,0x51,  /* 00000340    "IRQ1.IRQ" */
-    0x31,0x60,0x76,0x60,0x70,0x60,0x50,0x49,  /* 00000348    "1`v`p`PI" */
-    0x52,0x42,0x5B,0x82,0x49,0x08,0x4C,0x4E,  /* 00000350    "RB[.I.LN" */
-    0x4B,0x43,0x08,0x5F,0x48,0x49,0x44,0x0C,  /* 00000358    "KC._HID." */
-    0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,  /* 00000360    "A...._UI" */
-    0x44,0x0A,0x03,0x14,0x1C,0x5F,0x53,0x54,  /* 00000368    "D...._ST" */
-    0x41,0x00,0x7B,0x50,0x49,0x52,0x43,0x0A,  /* 00000370    "A.{PIRC." */
-    0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80,  /* 00000378    ".`...`.." */
-    0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B,  /* 00000380    "........" */
-    0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4,  /* 00000388    ".._PRS.." */
-    0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44,  /* 00000390    "BUFA.._D" */
-    0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x43,  /* 00000398    "IS.}PIRC" */
-    0x0A,0x80,0x50,0x49,0x52,0x43,0x14,0x1A,  /* 000003A0    "..PIRC.." */
-    0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49,  /* 000003A8    "_CRS.{PI" */
-    0x52,0x43,0x0A,0x0F,0x60,0x79,0x01,0x60,  /* 000003B0    "RC..`y.`" */
-    0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46,  /* 000003B8    "IRQV.BUF" */
-    0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,  /* 000003C0    "B.._SRS." */
-    0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82,  /* 000003C8    ".h.IRQ1." */
-    0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70,  /* 000003D0    "IRQ1`v`p" */
-    0x60,0x50,0x49,0x52,0x43,0x5B,0x82,0x49,  /* 000003D8    "`PIRC[.I" */
-    0x08,0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48,  /* 000003E0    ".LNKD._H" */
-    0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,  /* 000003E8    "ID.A...." */
-    0x5F,0x55,0x49,0x44,0x0A,0x04,0x14,0x1C,  /* 000003F0    "_UID...." */
-    0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49,  /* 000003F8    "_STA.{PI" */
-    0x52,0x44,0x0A,0x80,0x60,0xA0,0x08,0x93,  /* 00000400    "RD..`..." */
-    0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04,  /* 00000408    "`......." */
-    0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52,  /* 00000410    "....._PR" */
-    0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14,  /* 00000418    "S..BUFA." */
-    0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,  /* 00000420    "._DIS.}P" */
-    0x49,0x52,0x44,0x0A,0x80,0x50,0x49,0x52,  /* 00000428    "IRD..PIR" */
-    0x44,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,  /* 00000430    "D.._CRS." */
-    0x7B,0x50,0x49,0x52,0x44,0x0A,0x0F,0x60,  /* 00000438    "{PIRD..`" */
-    0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4,  /* 00000440    "y.`IRQV." */
-    0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53,  /* 00000448    "BUFB.._S" */
-    0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52,  /* 00000450    "RS..h.IR" */
-    0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60,  /* 00000458    "Q1.IRQ1`" */
-    0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x44,  /* 00000460    "v`p`PIRD" */
-    0x14,0x16,0x5F,0x50,0x52,0x54,0x00,0xA0,  /* 00000468    ".._PRT.." */
-    0x0A,0x50,0x49,0x43,0x44,0xA4,0x50,0x52,  /* 00000470    ".PICD.PR" */
-    0x54,0x41,0xA4,0x50,0x52,0x54,0x50,0x08,  /* 00000478    "TA.PRTP." */
-    0x50,0x52,0x54,0x50,0x12,0x4D,0x11,0x14,  /* 00000480    "PRTP.M.." */
-    0x12,0x0B,0x04,0x0B,0xFF,0xFF,0x00,0x4C,  /* 00000488    ".......L" */
-    0x4E,0x4B,0x41,0x00,0x12,0x0B,0x04,0x0B,  /* 00000490    "NKA....." */
-    0xFF,0xFF,0x01,0x4C,0x4E,0x4B,0x42,0x00,  /* 00000498    "...LNKB." */
-    0x12,0x0C,0x04,0x0B,0xFF,0xFF,0x0A,0x02,  /* 000004A0    "........" */
-    0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0C,0x04,  /* 000004A8    "LNKC...." */
-    0x0B,0xFF,0xFF,0x0A,0x03,0x4C,0x4E,0x4B,  /* 000004B0    ".....LNK" */
-    0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 000004B8    "D......." */
-    0x01,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,  /* 000004C0    "...LNKB." */
-    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01,0x00,  /* 000004C8    "........" */
-    0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,  /* 000004D0    ".LNKC..." */
-    0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02,  /* 000004D8    "........" */
-    0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,  /* 000004E0    "LNKD...." */
-    0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03,0x4C,  /* 000004E8    ".......L" */
-    0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,  /* 000004F0    "NKA....." */
-    0xFF,0xFF,0x02,0x00,0x00,0x4C,0x4E,0x4B,  /* 000004F8    ".....LNK" */
-    0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 00000500    "C......." */
-    0x02,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,  /* 00000508    "...LNKD." */
-    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00,  /* 00000510    "........" */
-    0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,  /* 00000518    "..LNKA.." */
-    0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A,  /* 00000520    "........" */
-    0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,  /* 00000528    ".LNKB..." */
-    0x04,0x0C,0xFF,0xFF,0x03,0x00,0x00,0x4C,  /* 00000530    ".......L" */
-    0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,  /* 00000538    "NKD....." */
-    0xFF,0xFF,0x03,0x00,0x01,0x4C,0x4E,0x4B,  /* 00000540    ".....LNK" */
-    0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 00000548    "A......." */
-    0x03,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,  /* 00000550    "....LNKB" */
-    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03,  /* 00000558    "........" */
-    0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,  /* 00000560    "...LNKC." */
-    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00,  /* 00000568    "........" */
-    0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,  /* 00000570    ".LNKA..." */
-    0x04,0x0C,0xFF,0xFF,0x04,0x00,0x01,0x4C,  /* 00000578    ".......L" */
-    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 00000580    "NKB....." */
-    0xFF,0xFF,0x04,0x00,0x0A,0x02,0x4C,0x4E,  /* 00000588    "......LN" */
-    0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 00000590    "KC......" */
-    0xFF,0x04,0x00,0x0A,0x03,0x4C,0x4E,0x4B,  /* 00000598    ".....LNK" */
-    0x44,0x00,0x08,0x50,0x52,0x54,0x41,0x12,  /* 000005A0    "D..PRTA." */
-    0x32,0x04,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 000005A8    "2......." */
-    0x01,0x00,0x00,0x00,0x0A,0x05,0x12,0x0B,  /* 000005B0    "........" */
-    0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,0x00,  /* 000005B8    "........" */
-    0x0A,0x07,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 000005C0    "........" */
-    0x03,0x00,0x00,0x00,0x0A,0x0A,0x12,0x0B,  /* 000005C8    "........" */
-    0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00,0x00,  /* 000005D0    "........" */
-    0x0A,0x0B,0x5B,0x82,0x48,0x31,0x49,0x53,  /* 000005D8    "..[.H1IS" */
-    0x41,0x5F,0x08,0x5F,0x41,0x44,0x52,0x00,  /* 000005E0    "A_._ADR." */
-    0x5B,0x80,0x50,0x49,0x52,0x51,0x02,0x0A,  /* 000005E8    "[.PIRQ.." */
-    0x60,0x0A,0x04,0x10,0x2E,0x5C,0x00,0x5B,  /* 000005F0    "`....\.[" */
-    0x81,0x29,0x5C,0x2F,0x04,0x5F,0x53,0x42,  /* 000005F8    ".)\/._SB" */
-    0x5F,0x50,0x43,0x49,0x30,0x49,0x53,0x41,  /* 00000600    "_PCI0ISA" */
-    0x5F,0x50,0x49,0x52,0x51,0x01,0x50,0x49,  /* 00000608    "_PIRQ.PI" */
-    0x52,0x41,0x08,0x50,0x49,0x52,0x42,0x08,  /* 00000610    "RA.PIRB." */
-    0x50,0x49,0x52,0x43,0x08,0x50,0x49,0x52,  /* 00000618    "PIRC.PIR" */
-    0x44,0x08,0x5B,0x82,0x46,0x0B,0x53,0x59,  /* 00000620    "D.[.F.SY" */
-    0x53,0x52,0x08,0x5F,0x48,0x49,0x44,0x0C,  /* 00000628    "SR._HID." */
-    0x41,0xD0,0x0C,0x02,0x08,0x5F,0x55,0x49,  /* 00000630    "A...._UI" */
-    0x44,0x01,0x08,0x43,0x52,0x53,0x5F,0x11,  /* 00000638    "D..CRS_." */
-    0x4E,0x08,0x0A,0x8A,0x47,0x01,0x10,0x00,  /* 00000640    "N...G..." */
-    0x10,0x00,0x00,0x10,0x47,0x01,0x22,0x00,  /* 00000648    "....G."." */
-    0x22,0x00,0x00,0x0C,0x47,0x01,0x30,0x00,  /* 00000650    ""...G.0." */
-    0x30,0x00,0x00,0x10,0x47,0x01,0x44,0x00,  /* 00000658    "0...G.D." */
-    0x44,0x00,0x00,0x1C,0x47,0x01,0x62,0x00,  /* 00000660    "D...G.b." */
-    0x62,0x00,0x00,0x02,0x47,0x01,0x65,0x00,  /* 00000668    "b...G.e." */
-    0x65,0x00,0x00,0x0B,0x47,0x01,0x72,0x00,  /* 00000670    "e...G.r." */
-    0x72,0x00,0x00,0x0E,0x47,0x01,0x80,0x00,  /* 00000678    "r...G..." */
-    0x80,0x00,0x00,0x01,0x47,0x01,0x84,0x00,  /* 00000680    "....G..." */
-    0x84,0x00,0x00,0x03,0x47,0x01,0x88,0x00,  /* 00000688    "....G..." */
-    0x88,0x00,0x00,0x01,0x47,0x01,0x8C,0x00,  /* 00000690    "....G..." */
-    0x8C,0x00,0x00,0x03,0x47,0x01,0x90,0x00,  /* 00000698    "....G..." */
-    0x90,0x00,0x00,0x10,0x47,0x01,0xA2,0x00,  /* 000006A0    "....G..." */
-    0xA2,0x00,0x00,0x1C,0x47,0x01,0xE0,0x00,  /* 000006A8    "....G..." */
-    0xE0,0x00,0x00,0x10,0x47,0x01,0xA0,0x08,  /* 000006B0    "....G..." */
-    0xA0,0x08,0x00,0x04,0x47,0x01,0xC0,0x0C,  /* 000006B8    "....G..." */
-    0xC0,0x0C,0x00,0x10,0x47,0x01,0xD0,0x04,  /* 000006C0    "....G..." */
-    0xD0,0x04,0x00,0x02,0x79,0x00,0x14,0x0B,  /* 000006C8    "....y..." */
-    0x5F,0x43,0x52,0x53,0x00,0xA4,0x43,0x52,  /* 000006D0    "_CRS..CR" */
-    0x53,0x5F,0x5B,0x82,0x2B,0x50,0x49,0x43,  /* 000006D8    "S_[.+PIC" */
-    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0B,0x41,  /* 000006E0    "_._HID.A" */
-    0xD0,0x08,0x5F,0x43,0x52,0x53,0x11,0x18,  /* 000006E8    ".._CRS.." */
-    0x0A,0x15,0x47,0x01,0x20,0x00,0x20,0x00,  /* 000006F0    "..G. . ." */
-    0x01,0x02,0x47,0x01,0xA0,0x00,0xA0,0x00,  /* 000006F8    "..G....." */
-    0x01,0x02,0x22,0x04,0x00,0x79,0x00,0x5B,  /* 00000700    ".."..y.[" */
-    0x82,0x47,0x05,0x44,0x4D,0x41,0x30,0x08,  /* 00000708    ".G.DMA0." */
-    0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x02,  /* 00000710    "_HID.A.." */
-    0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x41,  /* 00000718    ".._CRS.A" */
-    0x04,0x0A,0x3D,0x2A,0x10,0x04,0x47,0x01,  /* 00000720    "..=*..G." */
-    0x00,0x00,0x00,0x00,0x00,0x10,0x47,0x01,  /* 00000728    "......G." */
-    0x81,0x00,0x81,0x00,0x00,0x03,0x47,0x01,  /* 00000730    "......G." */
-    0x87,0x00,0x87,0x00,0x00,0x01,0x47,0x01,  /* 00000738    "......G." */
-    0x89,0x00,0x89,0x00,0x00,0x03,0x47,0x01,  /* 00000740    "......G." */
-    0x8F,0x00,0x8F,0x00,0x00,0x01,0x47,0x01,  /* 00000748    "......G." */
-    0xC0,0x00,0xC0,0x00,0x00,0x20,0x47,0x01,  /* 00000750    "..... G." */
-    0x80,0x04,0x80,0x04,0x00,0x10,0x79,0x00,  /* 00000758    "......y." */
-    0x5B,0x82,0x25,0x54,0x4D,0x52,0x5F,0x08,  /* 00000760    "[.%TMR_." */
-    0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x01,  /* 00000768    "_HID.A.." */
-    0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x10,  /* 00000770    ".._CRS.." */
-    0x0A,0x0D,0x47,0x01,0x40,0x00,0x40,0x00,  /* 00000778    "..G.@.@." */
-    0x00,0x04,0x22,0x01,0x00,0x79,0x00,0x5B,  /* 00000780    ".."..y.[" */
-    0x82,0x25,0x52,0x54,0x43,0x5F,0x08,0x5F,  /* 00000788    ".%RTC_._" */
-    0x48,0x49,0x44,0x0C,0x41,0xD0,0x0B,0x00,  /* 00000790    "HID.A..." */
-    0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A,  /* 00000798    "._CRS..." */
-    0x0D,0x47,0x01,0x70,0x00,0x70,0x00,0x00,  /* 000007A0    ".G.p.p.." */
-    0x02,0x22,0x00,0x01,0x79,0x00,0x5B,0x82,  /* 000007A8    "."..y.[." */
-    0x22,0x53,0x50,0x4B,0x52,0x08,0x5F,0x48,  /* 000007B0    ""SPKR._H" */
-    0x49,0x44,0x0C,0x41,0xD0,0x08,0x00,0x08,  /* 000007B8    "ID.A...." */
-    0x5F,0x43,0x52,0x53,0x11,0x0D,0x0A,0x0A,  /* 000007C0    "_CRS...." */
-    0x47,0x01,0x61,0x00,0x61,0x00,0x00,0x01,  /* 000007C8    "G.a.a..." */
-    0x79,0x00,0x5B,0x82,0x31,0x50,0x53,0x32,  /* 000007D0    "y.[.1PS2" */
-    0x4D,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,  /* 000007D8    "M._HID.A" */
-    0xD0,0x0F,0x13,0x08,0x5F,0x43,0x49,0x44,  /* 000007E0    "...._CID" */
-    0x0C,0x41,0xD0,0x0F,0x13,0x14,0x09,0x5F,  /* 000007E8    ".A....._" */
-    0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,  /* 000007F0    "STA....." */
-    0x5F,0x43,0x52,0x53,0x11,0x08,0x0A,0x05,  /* 000007F8    "_CRS...." */
-    0x22,0x00,0x10,0x79,0x00,0x5B,0x82,0x42,  /* 00000800    ""..y.[.B" */
-    0x04,0x50,0x53,0x32,0x4B,0x08,0x5F,0x48,  /* 00000808    ".PS2K._H" */
-    0x49,0x44,0x0C,0x41,0xD0,0x03,0x03,0x08,  /* 00000810    "ID.A...." */
-    0x5F,0x43,0x49,0x44,0x0C,0x41,0xD0,0x03,  /* 00000818    "_CID.A.." */
-    0x0B,0x14,0x09,0x5F,0x53,0x54,0x41,0x00,  /* 00000820    "..._STA." */
-    0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53,  /* 00000828    "...._CRS" */
-    0x11,0x18,0x0A,0x15,0x47,0x01,0x60,0x00,  /* 00000830    "....G.`." */
-    0x60,0x00,0x00,0x01,0x47,0x01,0x64,0x00,  /* 00000838    "`...G.d." */
-    0x64,0x00,0x00,0x01,0x22,0x02,0x00,0x79,  /* 00000840    "d..."..y" */
-    0x00,0x5B,0x82,0x3A,0x46,0x44,0x43,0x30,  /* 00000848    ".[.:FDC0" */
-    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 00000850    "._HID.A." */
-    0x07,0x00,0x14,0x09,0x5F,0x53,0x54,0x41,  /* 00000858    "...._STA" */
-    0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,  /* 00000860    "....._CR" */
-    0x53,0x11,0x1B,0x0A,0x18,0x47,0x01,0xF0,  /* 00000868    "S....G.." */
-    0x03,0xF0,0x03,0x01,0x06,0x47,0x01,0xF7,  /* 00000870    ".....G.." */
-    0x03,0xF7,0x03,0x01,0x01,0x22,0x40,0x00,  /* 00000878    "....."@." */
-    0x2A,0x04,0x00,0x79,0x00,0x5B,0x82,0x35,  /* 00000880    "*..y.[.5" */
-    0x55,0x41,0x52,0x31,0x08,0x5F,0x48,0x49,  /* 00000888    "UAR1._HI" */
-    0x44,0x0C,0x41,0xD0,0x05,0x01,0x08,0x5F,  /* 00000890    "D.A...._" */
-    0x55,0x49,0x44,0x01,0x14,0x09,0x5F,0x53,  /* 00000898    "UID..._S" */
-    0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,  /* 000008A0    "TA....._" */
-    0x43,0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,  /* 000008A8    "CRS....G" */
-    0x01,0xF8,0x03,0xF8,0x03,0x01,0x08,0x22,  /* 000008B0    "......."" */
-    0x10,0x00,0x79,0x00,0x5B,0x82,0x36,0x4C,  /* 000008B8    "..y.[.6L" */
-    0x54,0x50,0x31,0x08,0x5F,0x48,0x49,0x44,  /* 000008C0    "TP1._HID" */
-    0x0C,0x41,0xD0,0x04,0x00,0x08,0x5F,0x55,  /* 000008C8    ".A...._U" */
-    0x49,0x44,0x0A,0x02,0x14,0x09,0x5F,0x53,  /* 000008D0    "ID...._S" */
-    0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,  /* 000008D8    "TA....._" */
-    0x43,0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,  /* 000008E0    "CRS....G" */
-    0x01,0x78,0x03,0x78,0x03,0x08,0x08,0x22,  /* 000008E8    ".x.x..."" */
-    0x80,0x00,0x79,0x00,
+    0x5B,0x82,0x48,0x08,0x4C,0x4E,0x4B,0x41,  /* 00000208    "[.H.LNKA" */
+    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 00000210    "._HID.A." */
+    0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x01,  /* 00000218    "..._UID." */
+    0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,  /* 00000220    ".._STA.{" */
+    0x50,0x49,0x52,0x41,0x0A,0x80,0x60,0xA0,  /* 00000228    "PIRA..`." */
+    0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,  /* 00000230    "..`....." */
+    0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,  /* 00000238    "......._" */
+    0x50,0x52,0x53,0x00,0xA4,0x42,0x55,0x46,  /* 00000240    "PRS..BUF" */
+    0x41,0x14,0x11,0x5F,0x44,0x49,0x53,0x00,  /* 00000248    "A.._DIS." */
+    0x7D,0x50,0x49,0x52,0x41,0x0A,0x80,0x50,  /* 00000250    "}PIRA..P" */
+    0x49,0x52,0x41,0x14,0x1A,0x5F,0x43,0x52,  /* 00000258    "IRA.._CR" */
+    0x53,0x00,0x7B,0x50,0x49,0x52,0x41,0x0A,  /* 00000260    "S.{PIRA." */
+    0x0F,0x60,0x79,0x01,0x60,0x49,0x52,0x51,  /* 00000268    ".`y.`IRQ" */
+    0x56,0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,  /* 00000270    "V.BUFB.." */
+    0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,0x01,  /* 00000278    "_SRS..h." */
+    0x49,0x52,0x51,0x31,0x82,0x49,0x52,0x51,  /* 00000280    "IRQ1.IRQ" */
+    0x31,0x60,0x76,0x60,0x70,0x60,0x50,0x49,  /* 00000288    "1`v`p`PI" */
+    0x52,0x41,0x5B,0x82,0x49,0x08,0x4C,0x4E,  /* 00000290    "RA[.I.LN" */
+    0x4B,0x42,0x08,0x5F,0x48,0x49,0x44,0x0C,  /* 00000298    "KB._HID." */
+    0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,  /* 000002A0    "A...._UI" */
+    0x44,0x0A,0x02,0x14,0x1C,0x5F,0x53,0x54,  /* 000002A8    "D...._ST" */
+    0x41,0x00,0x7B,0x50,0x49,0x52,0x42,0x0A,  /* 000002B0    "A.{PIRB." */
+    0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80,  /* 000002B8    ".`...`.." */
+    0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B,  /* 000002C0    "........" */
+    0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4,  /* 000002C8    ".._PRS.." */
+    0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44,  /* 000002D0    "BUFA.._D" */
+    0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x42,  /* 000002D8    "IS.}PIRB" */
+    0x0A,0x80,0x50,0x49,0x52,0x42,0x14,0x1A,  /* 000002E0    "..PIRB.." */
+    0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49,  /* 000002E8    "_CRS.{PI" */
+    0x52,0x42,0x0A,0x0F,0x60,0x79,0x01,0x60,  /* 000002F0    "RB..`y.`" */
+    0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46,  /* 000002F8    "IRQV.BUF" */
+    0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,  /* 00000300    "B.._SRS." */
+    0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82,  /* 00000308    ".h.IRQ1." */
+    0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70,  /* 00000310    "IRQ1`v`p" */
+    0x60,0x50,0x49,0x52,0x42,0x5B,0x82,0x49,  /* 00000318    "`PIRB[.I" */
+    0x08,0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,  /* 00000320    ".LNKC._H" */
+    0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,  /* 00000328    "ID.A...." */
+    0x5F,0x55,0x49,0x44,0x0A,0x03,0x14,0x1C,  /* 00000330    "_UID...." */
+    0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49,  /* 00000338    "_STA.{PI" */
+    0x52,0x43,0x0A,0x80,0x60,0xA0,0x08,0x93,  /* 00000340    "RC..`..." */
+    0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04,  /* 00000348    "`......." */
+    0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52,  /* 00000350    "....._PR" */
+    0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14,  /* 00000358    "S..BUFA." */
+    0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,  /* 00000360    "._DIS.}P" */
+    0x49,0x52,0x43,0x0A,0x80,0x50,0x49,0x52,  /* 00000368    "IRC..PIR" */
+    0x43,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,  /* 00000370    "C.._CRS." */
+    0x7B,0x50,0x49,0x52,0x43,0x0A,0x0F,0x60,  /* 00000378    "{PIRC..`" */
+    0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4,  /* 00000380    "y.`IRQV." */
+    0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53,  /* 00000388    "BUFB.._S" */
+    0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52,  /* 00000390    "RS..h.IR" */
+    0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60,  /* 00000398    "Q1.IRQ1`" */
+    0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x43,  /* 000003A0    "v`p`PIRC" */
+    0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x44,  /* 000003A8    "[.I.LNKD" */
+    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 000003B0    "._HID.A." */
+    0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A,  /* 000003B8    "..._UID." */
+    0x04,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,  /* 000003C0    "..._STA." */
+    0x7B,0x50,0x49,0x52,0x44,0x0A,0x80,0x60,  /* 000003C8    "{PIRD..`" */
+    0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,  /* 000003D0    "...`...." */
+    0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,  /* 000003D8    "........" */
+    0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55,  /* 000003E0    "_PRS..BU" */
+    0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53,  /* 000003E8    "FA.._DIS" */
+    0x00,0x7D,0x50,0x49,0x52,0x44,0x0A,0x80,  /* 000003F0    ".}PIRD.." */
+    0x50,0x49,0x52,0x44,0x14,0x1A,0x5F,0x43,  /* 000003F8    "PIRD.._C" */
+    0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x44,  /* 00000400    "RS.{PIRD" */
+    0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52,  /* 00000408    "..`y.`IR" */
+    0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14,  /* 00000410    "QV.BUFB." */
+    0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,  /* 00000418    "._SRS..h" */
+    0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52,  /* 00000420    ".IRQ1.IR" */
+    0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50,  /* 00000428    "Q1`v`p`P" */
+    0x49,0x52,0x44,0x14,0x16,0x5F,0x50,0x52,  /* 00000430    "IRD.._PR" */
+    0x54,0x00,0xA0,0x0A,0x50,0x49,0x43,0x44,  /* 00000438    "T...PICD" */
+    0xA4,0x50,0x52,0x54,0x41,0xA4,0x50,0x52,  /* 00000440    ".PRTA.PR" */
+    0x54,0x50,0x08,0x50,0x52,0x54,0x50,0x12,  /* 00000448    "TP.PRTP." */
+    0x4B,0x39,0x40,0x12,0x0B,0x04,0x0B,0xFF,  /* 00000450    "K9@....." */
+    0xFF,0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,  /* 00000458    "..LNKA.." */
+    0x0B,0x04,0x0B,0xFF,0xFF,0x01,0x4C,0x4E,  /* 00000460    "......LN" */
+    0x4B,0x42,0x00,0x12,0x0C,0x04,0x0B,0xFF,  /* 00000468    "KB......" */
+    0xFF,0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,  /* 00000470    "...LNKC." */
+    0x12,0x0C,0x04,0x0B,0xFF,0xFF,0x0A,0x03,  /* 00000478    "........" */
+    0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,  /* 00000480    "LNKD...." */
+    0x0C,0xFF,0xFF,0x01,0x00,0x00,0x4C,0x4E,  /* 00000488    "......LN" */
+    0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000490    "KB......" */
+    0xFF,0x01,0x00,0x01,0x4C,0x4E,0x4B,0x43,  /* 00000498    "....LNKC" */
+    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,  /* 000004A0    "........" */
+    0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,  /* 000004A8    "...LNKD." */
+    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,  /* 000004B0    "........" */
+    0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,  /* 000004B8    "..LNKA.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,  /* 000004C0    "........" */
+    0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,  /* 000004C8    "LNKC...." */
+    0x0C,0xFF,0xFF,0x02,0x00,0x01,0x4C,0x4E,  /* 000004D0    "......LN" */
+    0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 000004D8    "KD......" */
+    0xFF,0x02,0x00,0x0A,0x02,0x4C,0x4E,0x4B,  /* 000004E0    ".....LNK" */
+    0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 000004E8    "A......." */
+    0x02,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,  /* 000004F0    "....LNKB" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,  /* 000004F8    "........" */
+    0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,  /* 00000500    "..LNKD.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,  /* 00000508    "........" */
+    0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,  /* 00000510    "LNKA...." */
+    0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x02,0x4C,  /* 00000518    ".......L" */
+    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 00000520    "NKB....." */
+    0xFF,0xFF,0x03,0x00,0x0A,0x03,0x4C,0x4E,  /* 00000528    "......LN" */
+    0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000530    "KC......" */
+    0xFF,0x04,0x00,0x00,0x4C,0x4E,0x4B,0x41,  /* 00000538    "....LNKA" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,  /* 00000540    "........" */
+    0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,  /* 00000548    "..LNKB.." */
+    0x0E,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,  /* 00000550    "........" */
+    0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,  /* 00000558    ".LNKC..." */
+    0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03,  /* 00000560    "........" */
+    0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,  /* 00000568    "LNKD...." */
+    0x0C,0xFF,0xFF,0x05,0x00,0x00,0x4C,0x4E,  /* 00000570    "......LN" */
+    0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000578    "KB......" */
+    0xFF,0x05,0x00,0x01,0x4C,0x4E,0x4B,0x43,  /* 00000580    "....LNKC" */
+    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,  /* 00000588    "........" */
+    0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,  /* 00000590    "...LNKD." */
+    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,  /* 00000598    "........" */
+    0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,  /* 000005A0    "..LNKA.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x00,  /* 000005A8    "........" */
+    0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,  /* 000005B0    "LNKC...." */
+    0x0C,0xFF,0xFF,0x06,0x00,0x01,0x4C,0x4E,  /* 000005B8    "......LN" */
+    0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 000005C0    "KD......" */
+    0xFF,0x06,0x00,0x0A,0x02,0x4C,0x4E,0x4B,  /* 000005C8    ".....LNK" */
+    0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 000005D0    "A......." */
+    0x06,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,  /* 000005D8    "....LNKB" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x07,  /* 000005E0    "........" */
+    0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,  /* 000005E8    "..LNKD.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x07,0x00,0x01,  /* 000005F0    "........" */
+    0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,  /* 000005F8    "LNKA...." */
+    0x0C,0xFF,0xFF,0x07,0x00,0x0A,0x02,0x4C,  /* 00000600    ".......L" */
+    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 00000608    "NKB....." */
+    0xFF,0xFF,0x07,0x00,0x0A,0x03,0x4C,0x4E,  /* 00000610    "......LN" */
+    0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000618    "KC......" */
+    0xFF,0x08,0x00,0x00,0x4C,0x4E,0x4B,0x41,  /* 00000620    "....LNKA" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x08,  /* 00000628    "........" */
+    0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,  /* 00000630    "..LNKB.." */
+    0x0E,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A,  /* 00000638    "........" */
+    0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,  /* 00000640    ".LNKC..." */
+    0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A,0x03,  /* 00000648    "........" */
+    0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,  /* 00000650    "LNKD...." */
+    0x0C,0xFF,0xFF,0x09,0x00,0x00,0x4C,0x4E,  /* 00000658    "......LN" */
+    0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000660    "KB......" */
+    0xFF,0x09,0x00,0x01,0x4C,0x4E,0x4B,0x43,  /* 00000668    "....LNKC" */
+    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x09,  /* 00000670    "........" */
+    0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,  /* 00000678    "...LNKD." */
+    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x09,0x00,  /* 00000680    "........" */
+    0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,  /* 00000688    "..LNKA.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x00,  /* 00000690    "........" */
+    0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,  /* 00000698    "LNKC...." */
+    0x0C,0xFF,0xFF,0x0A,0x00,0x01,0x4C,0x4E,  /* 000006A0    "......LN" */
+    0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 000006A8    "KD......" */
+    0xFF,0x0A,0x00,0x0A,0x02,0x4C,0x4E,0x4B,  /* 000006B0    ".....LNK" */
+    0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 000006B8    "A......." */
+    0x0A,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,  /* 000006C0    "....LNKB" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0B,  /* 000006C8    "........" */
+    0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,  /* 000006D0    "..LNKD.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x01,  /* 000006D8    "........" */
+    0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,  /* 000006E0    "LNKA...." */
+    0x0C,0xFF,0xFF,0x0B,0x00,0x0A,0x02,0x4C,  /* 000006E8    ".......L" */
+    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 000006F0    "NKB....." */
+    0xFF,0xFF,0x0B,0x00,0x0A,0x03,0x4C,0x4E,  /* 000006F8    "......LN" */
+    0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000700    "KC......" */
+    0xFF,0x0C,0x00,0x00,0x4C,0x4E,0x4B,0x41,  /* 00000708    "....LNKA" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0C,  /* 00000710    "........" */
+    0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,  /* 00000718    "..LNKB.." */
+    0x0E,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A,  /* 00000720    "........" */
+    0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,  /* 00000728    ".LNKC..." */
+    0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A,0x03,  /* 00000730    "........" */
+    0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,  /* 00000738    "LNKD...." */
+    0x0C,0xFF,0xFF,0x0D,0x00,0x00,0x4C,0x4E,  /* 00000740    "......LN" */
+    0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,  /* 00000748    "KB......" */
+    0xFF,0x0D,0x00,0x01,0x4C,0x4E,0x4B,0x43,  /* 00000750    "....LNKC" */
+    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0D,  /* 00000758    "........" */
+    0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,  /* 00000760    "...LNKD." */
+    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0D,0x00,  /* 00000768    "........" */
+    0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,  /* 00000770    "..LNKA.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x00,  /* 00000778    "........" */
+    0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,  /* 00000780    "LNKC...." */
+    0x0C,0xFF,0xFF,0x0E,0x00,0x01,0x4C,0x4E,  /* 00000788    "......LN" */
+    0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 00000790    "KD......" */
+    0xFF,0x0E,0x00,0x0A,0x02,0x4C,0x4E,0x4B,  /* 00000798    ".....LNK" */
+    0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 000007A0    "A......." */
+    0x0E,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,  /* 000007A8    "....LNKB" */
+    0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0F,  /* 000007B0    "........" */
+    0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,  /* 000007B8    "..LNKD.." */
+    0x0D,0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x01,  /* 000007C0    "........" */
+    0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,  /* 000007C8    "LNKA...." */
+    0x0C,0xFF,0xFF,0x0F,0x00,0x0A,0x02,0x4C,  /* 000007D0    ".......L" */
+    0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,  /* 000007D8    "NKB....." */
+    0xFF,0xFF,0x0F,0x00,0x0A,0x03,0x4C,0x4E,  /* 000007E0    "......LN" */
+    0x4B,0x43,0x00,0x08,0x50,0x52,0x54,0x41,  /* 000007E8    "KC..PRTA" */
+    0x12,0x4B,0x31,0x40,0x12,0x09,0x04,0x0B,  /* 000007F0    ".K1@...." */
+    0xFF,0xFF,0x00,0x00,0x0A,0x10,0x12,0x09,  /* 000007F8    "........" */
+    0x04,0x0B,0xFF,0xFF,0x01,0x00,0x0A,0x11,  /* 00000800    "........" */
+    0x12,0x0A,0x04,0x0B,0xFF,0xFF,0x0A,0x02,  /* 00000808    "........" */
+    0x00,0x0A,0x12,0x12,0x0A,0x04,0x0B,0xFF,  /* 00000810    "........" */
+    0xFF,0x0A,0x03,0x00,0x0A,0x13,0x12,0x0B,  /* 00000818    "........" */
+    0x04,0x0C,0xFF,0xFF,0x01,0x00,0x00,0x00,  /* 00000820    "........" */
+    0x0A,0x14,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 00000828    "........" */
+    0x01,0x00,0x01,0x00,0x0A,0x15,0x12,0x0C,  /* 00000830    "........" */
+    0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02,  /* 00000838    "........" */
+    0x00,0x0A,0x16,0x12,0x0C,0x04,0x0C,0xFF,  /* 00000840    "........" */
+    0xFF,0x01,0x00,0x0A,0x03,0x00,0x0A,0x17,  /* 00000848    "........" */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x02,0x00,  /* 00000850    "........" */
+    0x00,0x00,0x0A,0x18,0x12,0x0B,0x04,0x0C,  /* 00000858    "........" */
+    0xFF,0xFF,0x02,0x00,0x01,0x00,0x0A,0x19,  /* 00000860    "........" */
+    0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x02,0x00,  /* 00000868    "........" */
+    0x0A,0x02,0x00,0x0A,0x1A,0x12,0x0C,0x04,  /* 00000870    "........" */
+    0x0C,0xFF,0xFF,0x02,0x00,0x0A,0x03,0x00,  /* 00000878    "........" */
+    0x0A,0x1B,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 00000880    "........" */
+    0x03,0x00,0x00,0x00,0x0A,0x1C,0x12,0x0B,  /* 00000888    "........" */
+    0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,0x00,  /* 00000890    "........" */
+    0x0A,0x1D,0x12,0x0C,0x04,0x0C,0xFF,0xFF,  /* 00000898    "........" */
+    0x03,0x00,0x0A,0x02,0x00,0x0A,0x1E,0x12,  /* 000008A0    "........" */
+    0x0C,0x04,0x0C,0xFF,0xFF,0x03,0x00,0x0A,  /* 000008A8    "........" */
+    0x03,0x00,0x0A,0x1F,0x12,0x0B,0x04,0x0C,  /* 000008B0    "........" */
+    0xFF,0xFF,0x04,0x00,0x00,0x00,0x0A,0x20,  /* 000008B8    "....... " */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x04,0x00,  /* 000008C0    "........" */
+    0x01,0x00,0x0A,0x21,0x12,0x0C,0x04,0x0C,  /* 000008C8    "...!...." */
+    0xFF,0xFF,0x04,0x00,0x0A,0x02,0x00,0x0A,  /* 000008D0    "........" */
+    0x22,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x04,  /* 000008D8    ""......." */
+    0x00,0x0A,0x03,0x00,0x0A,0x23,0x12,0x0B,  /* 000008E0    ".....#.." */
+    0x04,0x0C,0xFF,0xFF,0x05,0x00,0x00,0x00,  /* 000008E8    "........" */
+    0x0A,0x24,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 000008F0    ".$......" */
+    0x05,0x00,0x01,0x00,0x0A,0x25,0x12,0x0C,  /* 000008F8    ".....%.." */
+    0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x02,  /* 00000900    "........" */
+    0x00,0x0A,0x26,0x12,0x0C,0x04,0x0C,0xFF,  /* 00000908    "..&....." */
+    0xFF,0x05,0x00,0x0A,0x03,0x00,0x0A,0x27,  /* 00000910    ".......'" */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x06,0x00,  /* 00000918    "........" */
+    0x00,0x00,0x0A,0x28,0x12,0x0B,0x04,0x0C,  /* 00000920    "...(...." */
+    0xFF,0xFF,0x06,0x00,0x01,0x00,0x0A,0x29,  /* 00000928    ".......)" */
+    0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x06,0x00,  /* 00000930    "........" */
+    0x0A,0x02,0x00,0x0A,0x2A,0x12,0x0C,0x04,  /* 00000938    "....*..." */
+    0x0C,0xFF,0xFF,0x06,0x00,0x0A,0x03,0x00,  /* 00000940    "........" */
+    0x0A,0x2B,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 00000948    ".+......" */
+    0x07,0x00,0x00,0x00,0x0A,0x2C,0x12,0x0B,  /* 00000950    ".....,.." */
+    0x04,0x0C,0xFF,0xFF,0x07,0x00,0x01,0x00,  /* 00000958    "........" */
+    0x0A,0x2D,0x12,0x0C,0x04,0x0C,0xFF,0xFF,  /* 00000960    ".-......" */
+    0x07,0x00,0x0A,0x02,0x00,0x0A,0x2E,0x12,  /* 00000968    "........" */
+    0x0C,0x04,0x0C,0xFF,0xFF,0x07,0x00,0x0A,  /* 00000970    "........" */
+    0x03,0x00,0x0A,0x2F,0x12,0x0B,0x04,0x0C,  /* 00000978    ".../...." */
+    0xFF,0xFF,0x08,0x00,0x00,0x00,0x0A,0x11,  /* 00000980    "........" */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x08,0x00,  /* 00000988    "........" */
+    0x01,0x00,0x0A,0x12,0x12,0x0C,0x04,0x0C,  /* 00000990    "........" */
+    0xFF,0xFF,0x08,0x00,0x0A,0x02,0x00,0x0A,  /* 00000998    "........" */
+    0x13,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x08,  /* 000009A0    "........" */
+    0x00,0x0A,0x03,0x00,0x0A,0x14,0x12,0x0B,  /* 000009A8    "........" */
+    0x04,0x0C,0xFF,0xFF,0x09,0x00,0x00,0x00,  /* 000009B0    "........" */
+    0x0A,0x15,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 000009B8    "........" */
+    0x09,0x00,0x01,0x00,0x0A,0x16,0x12,0x0C,  /* 000009C0    "........" */
+    0x04,0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x02,  /* 000009C8    "........" */
+    0x00,0x0A,0x17,0x12,0x0C,0x04,0x0C,0xFF,  /* 000009D0    "........" */
+    0xFF,0x09,0x00,0x0A,0x03,0x00,0x0A,0x18,  /* 000009D8    "........" */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0A,0x00,  /* 000009E0    "........" */
+    0x00,0x00,0x0A,0x19,0x12,0x0B,0x04,0x0C,  /* 000009E8    "........" */
+    0xFF,0xFF,0x0A,0x00,0x01,0x00,0x0A,0x1A,  /* 000009F0    "........" */
+    0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0A,0x00,  /* 000009F8    "........" */
+    0x0A,0x02,0x00,0x0A,0x1B,0x12,0x0C,0x04,  /* 00000A00    "........" */
+    0x0C,0xFF,0xFF,0x0A,0x00,0x0A,0x03,0x00,  /* 00000A08    "........" */
+    0x0A,0x1C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 00000A10    "........" */
+    0x0B,0x00,0x00,0x00,0x0A,0x1D,0x12,0x0B,  /* 00000A18    "........" */
+    0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x01,0x00,  /* 00000A20    "........" */
+    0x0A,0x1E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,  /* 00000A28    "........" */
+    0x0B,0x00,0x0A,0x02,0x00,0x0A,0x1F,0x12,  /* 00000A30    "........" */
+    0x0C,0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x0A,  /* 00000A38    "........" */
+    0x03,0x00,0x0A,0x20,0x12,0x0B,0x04,0x0C,  /* 00000A40    "... ...." */
+    0xFF,0xFF,0x0C,0x00,0x00,0x00,0x0A,0x21,  /* 00000A48    ".......!" */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0C,0x00,  /* 00000A50    "........" */
+    0x01,0x00,0x0A,0x22,0x12,0x0C,0x04,0x0C,  /* 00000A58    "..."...." */
+    0xFF,0xFF,0x0C,0x00,0x0A,0x02,0x00,0x0A,  /* 00000A60    "........" */
+    0x23,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0C,  /* 00000A68    "#......." */
+    0x00,0x0A,0x03,0x00,0x0A,0x24,0x12,0x0B,  /* 00000A70    ".....$.." */
+    0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x00,0x00,  /* 00000A78    "........" */
+    0x0A,0x25,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 00000A80    ".%......" */
+    0x0D,0x00,0x01,0x00,0x0A,0x26,0x12,0x0C,  /* 00000A88    ".....&.." */
+    0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02,  /* 00000A90    "........" */
+    0x00,0x0A,0x27,0x12,0x0C,0x04,0x0C,0xFF,  /* 00000A98    "..'....." */
+    0xFF,0x0D,0x00,0x0A,0x03,0x00,0x0A,0x28,  /* 00000AA0    ".......(" */
+    0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0E,0x00,  /* 00000AA8    "........" */
+    0x00,0x00,0x0A,0x29,0x12,0x0B,0x04,0x0C,  /* 00000AB0    "...)...." */
+    0xFF,0xFF,0x0E,0x00,0x01,0x00,0x0A,0x2A,  /* 00000AB8    ".......*" */
+    0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0E,0x00,  /* 00000AC0    "........" */
+    0x0A,0x02,0x00,0x0A,0x2B,0x12,0x0C,0x04,  /* 00000AC8    "....+..." */
+    0x0C,0xFF,0xFF,0x0E,0x00,0x0A,0x03,0x00,  /* 00000AD0    "........" */
+    0x0A,0x2C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,  /* 00000AD8    ".,......" */
+    0x0F,0x00,0x00,0x00,0x0A,0x2D,0x12,0x0B,  /* 00000AE0    ".....-.." */
+    0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x01,0x00,  /* 00000AE8    "........" */
+    0x0A,0x2E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,  /* 00000AF0    "........" */
+    0x0F,0x00,0x0A,0x02,0x00,0x0A,0x2F,0x12,  /* 00000AF8    "....../." */
+    0x0C,0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x0A,  /* 00000B00    "........" */
+    0x03,0x00,0x0A,0x10,0x5B,0x82,0x4C,0x31,  /* 00000B08    "....[.L1" */
+    0x49,0x53,0x41,0x5F,0x08,0x5F,0x41,0x44,  /* 00000B10    "ISA_._AD" */
+    0x52,0x0C,0x00,0x00,0x01,0x00,0x5B,0x80,  /* 00000B18    "R.....[." */
+    0x50,0x49,0x52,0x51,0x02,0x0A,0x60,0x0A,  /* 00000B20    "PIRQ..`." */
+    0x04,0x10,0x2E,0x5C,0x00,0x5B,0x81,0x29,  /* 00000B28    "...\.[.)" */
+    0x5C,0x2F,0x04,0x5F,0x53,0x42,0x5F,0x50,  /* 00000B30    "\/._SB_P" */
+    0x43,0x49,0x30,0x49,0x53,0x41,0x5F,0x50,  /* 00000B38    "CI0ISA_P" */
+    0x49,0x52,0x51,0x01,0x50,0x49,0x52,0x41,  /* 00000B40    "IRQ.PIRA" */
+    0x08,0x50,0x49,0x52,0x42,0x08,0x50,0x49,  /* 00000B48    ".PIRB.PI" */
+    0x52,0x43,0x08,0x50,0x49,0x52,0x44,0x08,  /* 00000B50    "RC.PIRD." */
+    0x5B,0x82,0x46,0x0B,0x53,0x59,0x53,0x52,  /* 00000B58    "[.F.SYSR" */
+    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 00000B60    "._HID.A." */
+    0x0C,0x02,0x08,0x5F,0x55,0x49,0x44,0x01,  /* 00000B68    "..._UID." */
+    0x08,0x43,0x52,0x53,0x5F,0x11,0x4E,0x08,  /* 00000B70    ".CRS_.N." */
+    0x0A,0x8A,0x47,0x01,0x10,0x00,0x10,0x00,  /* 00000B78    "..G....." */
+    0x00,0x10,0x47,0x01,0x22,0x00,0x22,0x00,  /* 00000B80    "..G."."." */
+    0x00,0x0C,0x47,0x01,0x30,0x00,0x30,0x00,  /* 00000B88    "..G.0.0." */
+    0x00,0x10,0x47,0x01,0x44,0x00,0x44,0x00,  /* 00000B90    "..G.D.D." */
+    0x00,0x1C,0x47,0x01,0x62,0x00,0x62,0x00,  /* 00000B98    "..G.b.b." */
+    0x00,0x02,0x47,0x01,0x65,0x00,0x65,0x00,  /* 00000BA0    "..G.e.e." */
+    0x00,0x0B,0x47,0x01,0x72,0x00,0x72,0x00,  /* 00000BA8    "..G.r.r." */
+    0x00,0x0E,0x47,0x01,0x80,0x00,0x80,0x00,  /* 00000BB0    "..G....." */
+    0x00,0x01,0x47,0x01,0x84,0x00,0x84,0x00,  /* 00000BB8    "..G....." */
+    0x00,0x03,0x47,0x01,0x88,0x00,0x88,0x00,  /* 00000BC0    "..G....." */
+    0x00,0x01,0x47,0x01,0x8C,0x00,0x8C,0x00,  /* 00000BC8    "..G....." */
+    0x00,0x03,0x47,0x01,0x90,0x00,0x90,0x00,  /* 00000BD0    "..G....." */
+    0x00,0x10,0x47,0x01,0xA2,0x00,0xA2,0x00,  /* 00000BD8    "..G....." */
+    0x00,0x1C,0x47,0x01,0xE0,0x00,0xE0,0x00,  /* 00000BE0    "..G....." */
+    0x00,0x10,0x47,0x01,0xA0,0x08,0xA0,0x08,  /* 00000BE8    "..G....." */
+    0x00,0x04,0x47,0x01,0xC0,0x0C,0xC0,0x0C,  /* 00000BF0    "..G....." */
+    0x00,0x10,0x47,0x01,0xD0,0x04,0xD0,0x04,  /* 00000BF8    "..G....." */
+    0x00,0x02,0x79,0x00,0x14,0x0B,0x5F,0x43,  /* 00000C00    "..y..._C" */
+    0x52,0x53,0x00,0xA4,0x43,0x52,0x53,0x5F,  /* 00000C08    "RS..CRS_" */
+    0x5B,0x82,0x2B,0x50,0x49,0x43,0x5F,0x08,  /* 00000C10    "[.+PIC_." */
+    0x5F,0x48,0x49,0x44,0x0B,0x41,0xD0,0x08,  /* 00000C18    "_HID.A.." */
+    0x5F,0x43,0x52,0x53,0x11,0x18,0x0A,0x15,  /* 00000C20    "_CRS...." */
+    0x47,0x01,0x20,0x00,0x20,0x00,0x01,0x02,  /* 00000C28    "G. . ..." */
+    0x47,0x01,0xA0,0x00,0xA0,0x00,0x01,0x02,  /* 00000C30    "G......." */
+    0x22,0x04,0x00,0x79,0x00,0x5B,0x82,0x47,  /* 00000C38    ""..y.[.G" */
+    0x05,0x44,0x4D,0x41,0x30,0x08,0x5F,0x48,  /* 00000C40    ".DMA0._H" */
+    0x49,0x44,0x0C,0x41,0xD0,0x02,0x00,0x08,  /* 00000C48    "ID.A...." */
+    0x5F,0x43,0x52,0x53,0x11,0x41,0x04,0x0A,  /* 00000C50    "_CRS.A.." */
+    0x3D,0x2A,0x10,0x04,0x47,0x01,0x00,0x00,  /* 00000C58    "=*..G..." */
+    0x00,0x00,0x00,0x10,0x47,0x01,0x81,0x00,  /* 00000C60    "....G..." */
+    0x81,0x00,0x00,0x03,0x47,0x01,0x87,0x00,  /* 00000C68    "....G..." */
+    0x87,0x00,0x00,0x01,0x47,0x01,0x89,0x00,  /* 00000C70    "....G..." */
+    0x89,0x00,0x00,0x03,0x47,0x01,0x8F,0x00,  /* 00000C78    "....G..." */
+    0x8F,0x00,0x00,0x01,0x47,0x01,0xC0,0x00,  /* 00000C80    "....G..." */
+    0xC0,0x00,0x00,0x20,0x47,0x01,0x80,0x04,  /* 00000C88    "... G..." */
+    0x80,0x04,0x00,0x10,0x79,0x00,0x5B,0x82,  /* 00000C90    "....y.[." */
+    0x25,0x54,0x4D,0x52,0x5F,0x08,0x5F,0x48,  /* 00000C98    "%TMR_._H" */
+    0x49,0x44,0x0C,0x41,0xD0,0x01,0x00,0x08,  /* 00000CA0    "ID.A...." */
+    0x5F,0x43,0x52,0x53,0x11,0x10,0x0A,0x0D,  /* 00000CA8    "_CRS...." */
+    0x47,0x01,0x40,0x00,0x40,0x00,0x00,0x04,  /* 00000CB0    "G.@.@..." */
+    0x22,0x01,0x00,0x79,0x00,0x5B,0x82,0x25,  /* 00000CB8    ""..y.[.%" */
+    0x52,0x54,0x43,0x5F,0x08,0x5F,0x48,0x49,  /* 00000CC0    "RTC_._HI" */
+    0x44,0x0C,0x41,0xD0,0x0B,0x00,0x08,0x5F,  /* 00000CC8    "D.A...._" */
+    0x43,0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,  /* 00000CD0    "CRS....G" */
+    0x01,0x70,0x00,0x70,0x00,0x00,0x02,0x22,  /* 00000CD8    ".p.p..."" */
+    0x00,0x01,0x79,0x00,0x5B,0x82,0x22,0x53,  /* 00000CE0    "..y.[."S" */
+    0x50,0x4B,0x52,0x08,0x5F,0x48,0x49,0x44,  /* 00000CE8    "PKR._HID" */
+    0x0C,0x41,0xD0,0x08,0x00,0x08,0x5F,0x43,  /* 00000CF0    ".A...._C" */
+    0x52,0x53,0x11,0x0D,0x0A,0x0A,0x47,0x01,  /* 00000CF8    "RS....G." */
+    0x61,0x00,0x61,0x00,0x00,0x01,0x79,0x00,  /* 00000D00    "a.a...y." */
+    0x5B,0x82,0x31,0x50,0x53,0x32,0x4D,0x08,  /* 00000D08    "[.1PS2M." */
+    0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0F,  /* 00000D10    "_HID.A.." */
+    0x13,0x08,0x5F,0x43,0x49,0x44,0x0C,0x41,  /* 00000D18    ".._CID.A" */
+    0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53,0x54,  /* 00000D20    "....._ST" */
+    0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,  /* 00000D28    "A....._C" */
+    0x52,0x53,0x11,0x08,0x0A,0x05,0x22,0x00,  /* 00000D30    "RS...."." */
+    0x10,0x79,0x00,0x5B,0x82,0x42,0x04,0x50,  /* 00000D38    ".y.[.B.P" */
+    0x53,0x32,0x4B,0x08,0x5F,0x48,0x49,0x44,  /* 00000D40    "S2K._HID" */
+    0x0C,0x41,0xD0,0x03,0x03,0x08,0x5F,0x43,  /* 00000D48    ".A...._C" */
+    0x49,0x44,0x0C,0x41,0xD0,0x03,0x0B,0x14,  /* 00000D50    "ID.A...." */
+    0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,  /* 00000D58    "._STA..." */
+    0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x18,  /* 00000D60    ".._CRS.." */
+    0x0A,0x15,0x47,0x01,0x60,0x00,0x60,0x00,  /* 00000D68    "..G.`.`." */
+    0x00,0x01,0x47,0x01,0x64,0x00,0x64,0x00,  /* 00000D70    "..G.d.d." */
+    0x00,0x01,0x22,0x02,0x00,0x79,0x00,0x5B,  /* 00000D78    ".."..y.[" */
+    0x82,0x3A,0x46,0x44,0x43,0x30,0x08,0x5F,  /* 00000D80    ".:FDC0._" */
+    0x48,0x49,0x44,0x0C,0x41,0xD0,0x07,0x00,  /* 00000D88    "HID.A..." */
+    0x14,0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,  /* 00000D90    ".._STA.." */
+    0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,  /* 00000D98    "..._CRS." */
+    0x1B,0x0A,0x18,0x47,0x01,0xF0,0x03,0xF0,  /* 00000DA0    "...G...." */
+    0x03,0x01,0x06,0x47,0x01,0xF7,0x03,0xF7,  /* 00000DA8    "...G...." */
+    0x03,0x01,0x01,0x22,0x40,0x00,0x2A,0x04,  /* 00000DB0    "..."@.*." */
+    0x00,0x79,0x00,0x5B,0x82,0x35,0x55,0x41,  /* 00000DB8    ".y.[.5UA" */
+    0x52,0x31,0x08,0x5F,0x48,0x49,0x44,0x0C,  /* 00000DC0    "R1._HID." */
+    0x41,0xD0,0x05,0x01,0x08,0x5F,0x55,0x49,  /* 00000DC8    "A...._UI" */
+    0x44,0x01,0x14,0x09,0x5F,0x53,0x54,0x41,  /* 00000DD0    "D..._STA" */
+    0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,  /* 00000DD8    "....._CR" */
+    0x53,0x11,0x10,0x0A,0x0D,0x47,0x01,0xF8,  /* 00000DE0    "S....G.." */
+    0x03,0xF8,0x03,0x01,0x08,0x22,0x10,0x00,  /* 00000DE8    ".....".." */
+    0x79,0x00,0x5B,0x82,0x36,0x4C,0x54,0x50,  /* 00000DF0    "y.[.6LTP" */
+    0x31,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,  /* 00000DF8    "1._HID.A" */
+    0xD0,0x04,0x00,0x08,0x5F,0x55,0x49,0x44,  /* 00000E00    "...._UID" */
+    0x0A,0x02,0x14,0x09,0x5F,0x53,0x54,0x41,  /* 00000E08    "...._STA" */
+    0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,  /* 00000E10    "....._CR" */
+    0x53,0x11,0x10,0x0A,0x0D,0x47,0x01,0x78,  /* 00000E18    "S....G.x" */
+    0x03,0x78,0x03,0x08,0x08,0x22,0x80,0x00,  /* 00000E20    ".x...".." */
+    0x79,0x00,
 };
 int DsdtLen=sizeof(AmlCode);
diff -r b80f00215bba -r f555a90bcc37 tools/firmware/hvmloader/acpi/gen.c
--- a/tools/firmware/hvmloader/acpi/gen.c       Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/hvmloader/acpi/gen.c       Tue Nov 21 19:22:25 2006 +0000
@@ -23,6 +23,8 @@
 #define USAGE  "Usage: acpi_gen filename \n"                           \
                "       generage acpitable and write to the binary \n"  \
                "       filename - the binary name\n"
+
+#define ACPI_TABLE_SIZE (8*1024)
 
 int main(int argc, char **argv)
 {
diff -r b80f00215bba -r f555a90bcc37 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c      Tue Nov 21 19:22:25 2006 +0000
@@ -175,7 +175,7 @@ main(void)
        puts("Loading ROMBIOS ...\n");
        memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
 
-        create_mp_tables();
+       create_mp_tables();
        
        if (cirrus_check()) {
                puts("Loading Cirrus VGABIOS ...\n");
diff -r b80f00215bba -r f555a90bcc37 tools/firmware/hvmloader/mp_tables.c
--- a/tools/firmware/hvmloader/mp_tables.c      Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/hvmloader/mp_tables.c      Tue Nov 21 19:22:25 2006 +0000
@@ -28,6 +28,7 @@
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
 
+#include <acpi_utils.h>
 
 /* FIXME find a header that already has types defined!!! */
 typedef unsigned char  uint8_t;
@@ -77,20 +78,23 @@ typedef   signed long int64_t;
 
 #define BUS_TYPE_LENGTH        6
 #define BUS_TYPE_STR_ISA       "ISA   "
+#define BUS_TYPE_STR_PCI       "PCI   "
+
+#define BUS_ID_ISA             0
+#define BUS_ID_PCI             1
 
 #define LAPIC_BASE_ADDR        0xFEE00000
 
+#define IOAPIC_ID              0
 #define IOAPIC_VERSION         0x11
 #define IOAPIC_BASE_ADDR       0xFEC00000
-#define IOAPIC_FLAG_ENABLED   (1U << 0)
+#define IOAPIC_FLAG_ENABLED    (1U << 0)
 
 #define INTR_TYPE_INT          0
 #define INTR_TYPE_NMI          1
 #define INTR_TYPE_SMI          2
 #define INTR_TYPE_EXTINT       3
 
-#define INTR_FLAGS             0
-
 #define INTR_MAX_NR            16
 
 #include "util.h"
@@ -103,232 +107,206 @@ extern int get_vcpu_nr(void);  /* for th
 
 /* MP Floating Pointer Structure */
 struct mp_floating_pointer_struct {
-       uint8_t signature[4];
-       uint32_t mp_table;
-       uint8_t length;
-       uint8_t revision;
-       uint8_t checksum;
-       uint8_t feature[5];
+    uint8_t signature[4];
+    uint32_t mp_table;
+    uint8_t length;
+    uint8_t revision;
+    uint8_t checksum;
+    uint8_t feature[5];
 };
 
 /* MP Configuration Table */
 struct mp_config_table {
-       uint8_t signature[4];
-       uint16_t length;
-       uint8_t revision;
-       uint8_t checksum;
-       uint8_t oem_id[8];
-       uint8_t vendor_id[12];
-       uint32_t oem_table;
-       uint16_t oem_table_sz;
-       uint16_t nr_entries;
-       uint32_t lapic;
-       uint16_t extended_length;
-       uint8_t extended_checksum;
-       uint8_t reserved;
+    uint8_t signature[4];
+    uint16_t length;
+    uint8_t revision;
+    uint8_t checksum;
+    uint8_t oem_id[8];
+    uint8_t vendor_id[12];
+    uint32_t oem_table;
+    uint16_t oem_table_sz;
+    uint16_t nr_entries;
+    uint32_t lapic;
+    uint16_t extended_length;
+    uint8_t extended_checksum;
+    uint8_t reserved;
 };
 
 /* MP Processor Entry */
 struct mp_proc_entry {
-       uint8_t type;
-       uint8_t lapic_id;
-       uint8_t lapic_version;
-       uint8_t cpu_flags;
-       uint32_t cpu_signature;
-       uint32_t feature_flags;
-       uint8_t reserved[8];
+    uint8_t type;
+    uint8_t lapic_id;
+    uint8_t lapic_version;
+    uint8_t cpu_flags;
+    uint32_t cpu_signature;
+    uint32_t feature_flags;
+    uint8_t reserved[8];
 };
 
 /* MP Bus Entry */
 struct mp_bus_entry {
-       uint8_t type;
-       uint8_t bus_id;
-       uint8_t bus_type_str[6];
+    uint8_t type;
+    uint8_t bus_id;
+    uint8_t bus_type_str[6];
 };
 
 /* MP IOAPIC Entry */
 struct mp_ioapic_entry {
-       uint8_t type;
-       uint8_t ioapic_id;
-       uint8_t ioapic_version;
-       uint8_t ioapic_flags;
-       uint32_t ioapic_addr;
+    uint8_t type;
+    uint8_t ioapic_id;
+    uint8_t ioapic_version;
+    uint8_t ioapic_flags;
+    uint32_t ioapic_addr;
 };
 
 /* MP IO Interrupt Entry */
 struct mp_io_intr_entry {
-       uint8_t type;
-       uint8_t intr_type;
-       uint16_t io_intr_flags;
-       uint8_t src_bus_id;
-       uint8_t src_bus_irq;
-       uint8_t dst_ioapic_id;
-       uint8_t dst_ioapic_intin;
+    uint8_t type;
+    uint8_t intr_type;
+    uint16_t io_intr_flags;
+    uint8_t src_bus_id;
+    uint8_t src_bus_irq;
+    uint8_t dst_ioapic_id;
+    uint8_t dst_ioapic_intin;
 };
 
 /* MP Local Interrupt Entry */
 struct mp_local_intr_entry {
-       uint8_t type;
-       uint8_t intr_type;
-       uint16_t local_intr_flags;
-       uint8_t src_bus_id;
-       uint8_t src_bus_irq;
-       uint8_t dst_lapic_id;
-       uint8_t dst_lapic_lintin;
-};
-
-
-/* 
- * fill_mp_config_table - fills in the information for the MP config table
- *    
- * When calculating the length and nr_entries fields, keep in mind that there
- * are always 18 non-processor entries and N processor entries
- * 
- *    N vcpu entries
- *    1 bus entry 
- *    1 IOAPIC entry 
- * + 16 IO intr. entries
- * ----------------------
- * 18 + N total entries
- */
-void fill_mp_config_table(struct mp_config_table *mpct)
-{
-       int vcpu_nr;
-
-       vcpu_nr = get_vcpu_nr();
-
-       /* fill in the MP configuration table signature, "PCMP" */
-       mpct->signature[0] = 'P';
-       mpct->signature[1] = 'C';
-       mpct->signature[2] = 'M';
-       mpct->signature[3] = 'P';
-
-       mpct->length =    sizeof(struct mp_config_table)
-                       + vcpu_nr * sizeof(struct mp_proc_entry)
-                       + sizeof(struct mp_ioapic_entry)
-                       + sizeof(struct mp_bus_entry)
-                       + 16 * sizeof(struct mp_local_intr_entry);
-
-       mpct->revision = 4;
-
-       /* 
-        * We'll fill in the checksum later after all of the 
-        * entries have been created
-        */
-       mpct->checksum = 0;
-
-       /* fill in the OEM ID string, "_HVMCPU_" */
-       mpct->oem_id[0] = '_'; mpct->oem_id[3] = 'M'; mpct->oem_id[6] = 'U';
-       mpct->oem_id[1] = 'H'; mpct->oem_id[4] = 'C'; mpct->oem_id[7] = '_';
-       mpct->oem_id[2] = 'V'; mpct->oem_id[5] = 'P';
-
-       /* fill in the Vendor ID string, "XEN         " */
-       mpct->vendor_id[0] = 'X'; mpct->vendor_id[6] =  ' ';
-       mpct->vendor_id[1] = 'E'; mpct->vendor_id[7] =  ' ';
-       mpct->vendor_id[2] = 'N'; mpct->vendor_id[8] =  ' ';
-       mpct->vendor_id[3] = ' '; mpct->vendor_id[9] =  ' ';
-       mpct->vendor_id[4] = ' '; mpct->vendor_id[10] = ' ';
-       mpct->vendor_id[5] = ' '; mpct->vendor_id[11] = ' ';
-
-       mpct->oem_table = 0;
-       mpct->oem_table_sz = 0;
-
-       mpct->nr_entries = vcpu_nr + NR_NONPROC_ENTRIES;
-
-       mpct->lapic = LAPIC_BASE_ADDR;
-       mpct->extended_length = 0;
-       mpct->extended_checksum = 0;
-}
-
-
-/* calculates the checksum for the MP configuration table */
-void fill_mp_config_table_checksum(struct mp_config_table *mpct)
-{
-       int i;
-       uint8_t checksum;
-
-       checksum = 0;
-       for (i = 0; i < mpct->length; ++i)
-               checksum += ((uint8_t *)(mpct))[i];
-       mpct->checksum = -checksum;
-}
-
+    uint8_t type;
+    uint8_t intr_type;
+    uint16_t local_intr_flags;
+    uint8_t src_bus_id;
+    uint8_t src_bus_irq;
+    uint8_t dst_lapic_id;
+    uint8_t dst_lapic_lintin;
+};
+
+
+void fill_mp_config_table(struct mp_config_table *mpct, int length)
+{
+    int vcpu_nr, i;
+    uint8_t checksum;
+
+    vcpu_nr = get_vcpu_nr();
+
+    /* fill in the MP configuration table signature, "PCMP" */
+    mpct->signature[0] = 'P';
+    mpct->signature[1] = 'C';
+    mpct->signature[2] = 'M';
+    mpct->signature[3] = 'P';
+
+    mpct->length = length;
+
+    mpct->revision = 4;
+
+    /* fill in the OEM ID string, "_HVMCPU_" */
+    mpct->oem_id[0] = '_'; mpct->oem_id[3] = 'M'; mpct->oem_id[6] = 'U';
+    mpct->oem_id[1] = 'H'; mpct->oem_id[4] = 'C'; mpct->oem_id[7] = '_';
+    mpct->oem_id[2] = 'V'; mpct->oem_id[5] = 'P';
+
+    /* fill in the Vendor ID string, "XEN         " */
+    mpct->vendor_id[0] = 'X'; mpct->vendor_id[6] =  ' ';
+    mpct->vendor_id[1] = 'E'; mpct->vendor_id[7] =  ' ';
+    mpct->vendor_id[2] = 'N'; mpct->vendor_id[8] =  ' ';
+    mpct->vendor_id[3] = ' '; mpct->vendor_id[9] =  ' ';
+    mpct->vendor_id[4] = ' '; mpct->vendor_id[10] = ' ';
+    mpct->vendor_id[5] = ' '; mpct->vendor_id[11] = ' ';
+
+    mpct->oem_table = 0;
+    mpct->oem_table_sz = 0;
+
+    mpct->nr_entries = vcpu_nr + NR_NONPROC_ENTRIES;
+
+    mpct->lapic = LAPIC_BASE_ADDR;
+    mpct->extended_length = 0;
+    mpct->extended_checksum = 0;
+
+    /* Finally, fill in the checksum. */
+    mpct->checksum = checksum = 0;
+    for ( i = 0; i < length; i++ )
+        checksum += ((uint8_t *)(mpct))[i];
+    mpct->checksum = -checksum;
+}
 
 /* fills in an MP processor entry for VCPU 'vcpu_id' */
 void fill_mp_proc_entry(struct mp_proc_entry *mppe, int vcpu_id)
 {
-       mppe->type = ENTRY_TYPE_PROCESSOR;
-       mppe->lapic_id = vcpu_id;
-       mppe->lapic_version = 0x11;
-       mppe->cpu_flags = CPU_FLAG_ENABLED;
-       if (vcpu_id == 0)
-               mppe->cpu_flags |= CPU_FLAG_BSP;
-       mppe->cpu_signature = CPU_SIGNATURE;
-       mppe->feature_flags = CPU_FEATURES;
+    mppe->type = ENTRY_TYPE_PROCESSOR;
+    mppe->lapic_id = vcpu_id;
+    mppe->lapic_version = 0x11;
+    mppe->cpu_flags = CPU_FLAG_ENABLED;
+    if ( vcpu_id == 0 )
+        mppe->cpu_flags |= CPU_FLAG_BSP;
+    mppe->cpu_signature = CPU_SIGNATURE;
+    mppe->feature_flags = CPU_FEATURES;
 }
 
 
 /* fills in an MP bus entry of type 'type' and bus ID 'bus_id' */
 void fill_mp_bus_entry(struct mp_bus_entry *mpbe, int bus_id, const char *type)
 {
-       int i;
-
-       mpbe->type = ENTRY_TYPE_BUS;
-       mpbe->bus_id = bus_id;
-       for (i = 0; i < BUS_TYPE_LENGTH; ++i)
-               mpbe->bus_type_str[i] = type[i]; /* FIXME length check? */
+    int i;
+
+    mpbe->type = ENTRY_TYPE_BUS;
+    mpbe->bus_id = bus_id;
+    for ( i = 0; i < BUS_TYPE_LENGTH; i++ )
+        mpbe->bus_type_str[i] = type[i]; /* FIXME length check? */
 }
 
 
 /* fills in an MP IOAPIC entry for IOAPIC 'ioapic_id' */
 void fill_mp_ioapic_entry(struct mp_ioapic_entry *mpie, int ioapic_id)
 {
-       mpie->type = ENTRY_TYPE_IOAPIC;
-       mpie->ioapic_id = ioapic_id;
-       mpie->ioapic_version = IOAPIC_VERSION;
-       mpie->ioapic_flags = IOAPIC_FLAG_ENABLED;
-       mpie->ioapic_addr = IOAPIC_BASE_ADDR;
+    mpie->type = ENTRY_TYPE_IOAPIC;
+    mpie->ioapic_id = ioapic_id;
+    mpie->ioapic_version = IOAPIC_VERSION;
+    mpie->ioapic_flags = IOAPIC_FLAG_ENABLED;
+    mpie->ioapic_addr = IOAPIC_BASE_ADDR;
 }
 
 
 /* fills in an IO interrupt entry for IOAPIC 'ioapic_id' */
-void fill_mp_io_intr_entry(struct mp_io_intr_entry *mpiie,
-               int src_bus_irq, int ioapic_id, int dst_ioapic_intin)
-{
-       mpiie->type = ENTRY_TYPE_IO_INTR;
-       mpiie->intr_type = INTR_TYPE_INT;
-       mpiie->io_intr_flags = INTR_FLAGS;
-       mpiie->src_bus_id = 0;
-       mpiie->src_bus_irq = src_bus_irq;
-       mpiie->dst_ioapic_id = ioapic_id;
-       mpiie->dst_ioapic_intin = dst_ioapic_intin;
+void fill_mp_io_intr_entry(
+    struct mp_io_intr_entry *mpiie,
+    int src_bus_id, int src_bus_irq, int ioapic_id, int dst_ioapic_intin)
+{
+    mpiie->type = ENTRY_TYPE_IO_INTR;
+    mpiie->intr_type = INTR_TYPE_INT;
+    mpiie->io_intr_flags = 0;
+    /* IRQs 10 and 11 are PCI, so level triggered and active low. */
+    if ( (src_bus_irq == 10) || (src_bus_irq == 11) )
+        mpiie->io_intr_flags = 0xf;
+    mpiie->src_bus_id = src_bus_id;
+    mpiie->src_bus_irq = src_bus_irq;
+    mpiie->dst_ioapic_id = ioapic_id;
+    mpiie->dst_ioapic_intin = dst_ioapic_intin;
 }
 
 
 /* fill in the mp floating processor structure */
 void fill_mpfps(struct mp_floating_pointer_struct *mpfps, uint32_t mpct)
 {
-       int i;
-       uint8_t checksum;
-
-
-       mpfps->signature[0] = '_';
-       mpfps->signature[1] = 'M';
-       mpfps->signature[2] = 'P';
-       mpfps->signature[3] = '_';
-
-       mpfps->mp_table = mpct; 
-       mpfps->length = 1;
-       mpfps->revision = 4;
-       mpfps->checksum = 0;
-       for (i = 0; i < 5; ++i)
-               mpfps->feature[i] = 0;
-
-       /* compute the checksum for our new table */
-       checksum = 0;
-       for (i = 0; i < sizeof(struct mp_floating_pointer_struct); ++i)
-               checksum += ((uint8_t *)(mpfps))[i];
-       mpfps->checksum = -checksum;
+    int i;
+    uint8_t checksum;
+
+
+    mpfps->signature[0] = '_';
+    mpfps->signature[1] = 'M';
+    mpfps->signature[2] = 'P';
+    mpfps->signature[3] = '_';
+
+    mpfps->mp_table = mpct; 
+    mpfps->length = 1;
+    mpfps->revision = 4;
+    mpfps->checksum = 0;
+    for (i = 0; i < 5; ++i)
+        mpfps->feature[i] = 0;
+
+    /* compute the checksum for our new table */
+    checksum = 0;
+    for ( i = 0; i < sizeof(struct mp_floating_pointer_struct); i++ )
+        checksum += ((uint8_t *)(mpfps))[i];
+    mpfps->checksum = -checksum;
 }
 
 
@@ -340,88 +318,90 @@ void fill_mpfps(struct mp_floating_point
  */
 void* get_mp_table_start(void)
 {
-       char *bios_mem;
-       for (bios_mem = (char *)ROMBIOS_BEGIN; 
-            bios_mem != (char *)ROMBIOS_END; 
-            ++bios_mem)
-               if (bios_mem[0] == '_' && bios_mem[1] == '_' &&
-                   bios_mem[2] == '_' && bios_mem[3] == 'H' &&
-                   bios_mem[4] == 'V' && bios_mem[5] == 'M' &&
-                   bios_mem[6] == 'M' && bios_mem[7] == 'P')
-                       return bios_mem;
-
-       return (void *)-1;
+    char *bios_mem;
+
+    for ( bios_mem = (char *)ROMBIOS_BEGIN; 
+          bios_mem != (char *)ROMBIOS_END; 
+          bios_mem++ )
+    {
+        if ( bios_mem[0] == '_' && bios_mem[1] == '_' &&
+             bios_mem[2] == '_' && bios_mem[3] == 'H' &&
+             bios_mem[4] == 'V' && bios_mem[5] == 'M' &&
+             bios_mem[6] == 'M' && bios_mem[7] == 'P' )
+            return bios_mem;
+    }
+
+    return NULL;
 }
 
 
 /* recalculate the new ROMBIOS checksum after adding MP tables */
 void reset_bios_checksum(void)
 {
-       uint32_t i;
-       uint8_t checksum;
-
-       checksum = 0;
-       for (i = 0; i < ROMBIOS_MAXOFFSET; ++i)
-               checksum += ((uint8_t *)(ROMBIOS_BEGIN))[i];
-       
-       *((uint8_t *)(ROMBIOS_BEGIN + ROMBIOS_MAXOFFSET)) = -checksum;
+    uint32_t i;
+    uint8_t checksum;
+
+    checksum = 0;
+    for (i = 0; i < ROMBIOS_MAXOFFSET; ++i)
+        checksum += ((uint8_t *)(ROMBIOS_BEGIN))[i];
+
+    *((uint8_t *)(ROMBIOS_BEGIN + ROMBIOS_MAXOFFSET)) = -checksum;
 }
 
 
 /* create_mp_tables - creates MP tables for the guest based upon config data */
 void create_mp_tables(void)
 {
-       void *mp_table_base;
-       char *p;
-       struct mp_config_table *mp_config_table;
-       int vcpu_nr;
-       int i;
-
-       vcpu_nr = get_vcpu_nr();
-       
-       puts("Creating MP tables ...\n");
-
-       /* find the 'safe' place in ROMBIOS for the MP tables */
-       mp_table_base = get_mp_table_start();
-       if (mp_table_base == (void *)-1) {
-               puts("Couldn't find start point for MP tables\n");
-               return;
-       }
-       p = mp_table_base;
-
-       fill_mp_config_table((struct mp_config_table *)p);
-
-       /* save the location of the MP config table for a little later*/
-       mp_config_table = (struct mp_config_table *)p;
-       p += sizeof(struct mp_config_table);
-
-       for (i = 0; i < vcpu_nr; ++i) {
-               fill_mp_proc_entry((struct mp_proc_entry *)p, i);
-               p += sizeof(struct mp_proc_entry);
-       }
-
-       fill_mp_bus_entry((struct mp_bus_entry *)p, 0, BUS_TYPE_STR_ISA);
-       p += sizeof(struct mp_bus_entry);
-
-       fill_mp_ioapic_entry((struct mp_ioapic_entry *)p, vcpu_nr);
-       p += sizeof(struct mp_ioapic_entry);
-
-       for (i = 0; i < INTR_MAX_NR; ++i) {
-               fill_mp_io_intr_entry((struct mp_io_intr_entry *)p, 
-                               i, vcpu_nr, i);
-               p += sizeof(struct mp_io_intr_entry);
-       }
-
-       /* find the next 16-byte boundary to place the mp floating pointer */
-       while ((unsigned long)p & 0xF)
-               ++p;
-       
-       fill_mpfps((struct mp_floating_pointer_struct *)p, 
-                       (uint32_t)mp_table_base);
-
-       /* calculate the MP configuration table's checksum */
-       fill_mp_config_table_checksum(mp_config_table);
-
-       /* finally, recalculate the ROMBIOS checksum */
-       reset_bios_checksum();
-}
+    void *mp_table_base;
+    char *p;
+    int vcpu_nr, i, length;
+
+    vcpu_nr = get_vcpu_nr();
+
+    puts("Creating MP tables ...\n");
+
+    /* Find the 'safe' place in ROMBIOS for the MP tables. */
+    mp_table_base = get_mp_table_start();
+    if ( mp_table_base == NULL )
+    {
+        puts("Couldn't find start point for MP tables\n");
+        return;
+    }
+
+    p = mp_table_base + sizeof(struct mp_config_table);
+
+    for ( i = 0; i < vcpu_nr; i++ )
+    {
+        fill_mp_proc_entry((struct mp_proc_entry *)p, i);
+        p += sizeof(struct mp_proc_entry);
+    }
+
+    fill_mp_bus_entry((struct mp_bus_entry *)p, BUS_ID_ISA, BUS_TYPE_STR_ISA);
+    p += sizeof(struct mp_bus_entry);
+
+    fill_mp_bus_entry((struct mp_bus_entry *)p, BUS_ID_PCI, BUS_TYPE_STR_PCI);
+    p += sizeof(struct mp_bus_entry);
+
+    fill_mp_ioapic_entry((struct mp_ioapic_entry *)p, IOAPIC_ID);
+    p += sizeof(struct mp_ioapic_entry);
+
+    for ( i = 0; i < 16; i++ )
+    {
+        if ( i == 2 ) continue; /* skip the slave PIC connection */
+        fill_mp_io_intr_entry((struct mp_io_intr_entry *)p, 
+                              BUS_ID_ISA, i, IOAPIC_ID, i);
+        p += sizeof(struct mp_io_intr_entry);
+    }
+
+    length = p - (char *)mp_table_base;
+
+    /* find the next 16-byte boundary to place the mp floating pointer */
+    while ( (unsigned long)p & 0xF )
+        p++;
+
+    fill_mpfps((struct mp_floating_pointer_struct *)p, 
+               (uint32_t)mp_table_base);
+
+    fill_mp_config_table((struct mp_config_table *)mp_table_base, length);
+    reset_bios_checksum();
+}
diff -r b80f00215bba -r f555a90bcc37 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/firmware/rombios/rombios.c  Tue Nov 21 19:22:25 2006 +0000
@@ -9103,7 +9103,46 @@ pci_routing_table_structure:
   ;; first slot entry PCI-to-ISA (embedded)
   db 0 ;; pci bus number
   db 0x08 ;; pci device number (bit 7-3)
-  db 0x60 ;; link value INTA#: pointer into PCI2ISA config space
+  db 0x61 ;; link value INTA#: pointer into PCI2ISA config space
+  dw 0xdef8 ;; IRQ bitmap INTA# 
+  db 0x62 ;; link value INTB#
+  dw 0xdef8 ;; IRQ bitmap INTB# 
+  db 0x63 ;; link value INTC#
+  dw 0xdef8 ;; IRQ bitmap INTC# 
+  db 0x60 ;; link value INTD#
+  dw 0xdef8 ;; IRQ bitmap INTD#
+  db 0 ;; physical slot (0 = embedded)
+  db 0 ;; reserved
+  ;; second slot entry: 1st PCI slot
+  db 0 ;; pci bus number
+  db 0x10 ;; pci device number (bit 7-3)
+  db 0x62 ;; link value INTA#
+  dw 0xdef8 ;; IRQ bitmap INTA# 
+  db 0x63 ;; link value INTB#
+  dw 0xdef8 ;; IRQ bitmap INTB# 
+  db 0x60 ;; link value INTC#
+  dw 0xdef8 ;; IRQ bitmap INTC# 
+  db 0x61 ;; link value INTD#
+  dw 0xdef8 ;; IRQ bitmap INTD#
+  db 1 ;; physical slot (0 = embedded)
+  db 0 ;; reserved
+  ;; third slot entry: 2nd PCI slot
+  db 0 ;; pci bus number
+  db 0x18 ;; pci device number (bit 7-3)
+  db 0x63 ;; link value INTA#
+  dw 0xdef8 ;; IRQ bitmap INTA# 
+  db 0x60 ;; link value INTB#
+  dw 0xdef8 ;; IRQ bitmap INTB# 
+  db 0x61 ;; link value INTC#
+  dw 0xdef8 ;; IRQ bitmap INTC# 
+  db 0x62 ;; link value INTD#
+  dw 0xdef8 ;; IRQ bitmap INTD#
+  db 2 ;; physical slot (0 = embedded)
+  db 0 ;; reserved
+  ;; 4th slot entry: 3rd PCI slot
+  db 0 ;; pci bus number
+  db 0x20 ;; pci device number (bit 7-3)
+  db 0x60 ;; link value INTA#
   dw 0xdef8 ;; IRQ bitmap INTA# 
   db 0x61 ;; link value INTB#
   dw 0xdef8 ;; IRQ bitmap INTB# 
@@ -9111,11 +9150,11 @@ pci_routing_table_structure:
   dw 0xdef8 ;; IRQ bitmap INTC# 
   db 0x63 ;; link value INTD#
   dw 0xdef8 ;; IRQ bitmap INTD#
-  db 0 ;; physical slot (0 = embedded)
+  db 3 ;; physical slot (0 = embedded)
   db 0 ;; reserved
-  ;; second slot entry: 1st PCI slot
+  ;; 5th slot entry: 4rd PCI slot
   db 0 ;; pci bus number
-  db 0x10 ;; pci device number (bit 7-3)
+  db 0x28 ;; pci device number (bit 7-3)
   db 0x61 ;; link value INTA#
   dw 0xdef8 ;; IRQ bitmap INTA# 
   db 0x62 ;; link value INTB#
@@ -9124,11 +9163,11 @@ pci_routing_table_structure:
   dw 0xdef8 ;; IRQ bitmap INTC# 
   db 0x60 ;; link value INTD#
   dw 0xdef8 ;; IRQ bitmap INTD#
-  db 1 ;; physical slot (0 = embedded)
+  db 4 ;; physical slot (0 = embedded)
   db 0 ;; reserved
-  ;; third slot entry: 2nd PCI slot
+  ;; 6th slot entry: 5rd PCI slot
   db 0 ;; pci bus number
-  db 0x18 ;; pci device number (bit 7-3)
+  db 0x30 ;; pci device number (bit 7-3)
   db 0x62 ;; link value INTA#
   dw 0xdef8 ;; IRQ bitmap INTA# 
   db 0x63 ;; link value INTB#
@@ -9136,45 +9175,6 @@ pci_routing_table_structure:
   db 0x60 ;; link value INTC#
   dw 0xdef8 ;; IRQ bitmap INTC# 
   db 0x61 ;; link value INTD#
-  dw 0xdef8 ;; IRQ bitmap INTD#
-  db 2 ;; physical slot (0 = embedded)
-  db 0 ;; reserved
-  ;; 4th slot entry: 3rd PCI slot
-  db 0 ;; pci bus number
-  db 0x20 ;; pci device number (bit 7-3)
-  db 0x63 ;; link value INTA#
-  dw 0xdef8 ;; IRQ bitmap INTA# 
-  db 0x60 ;; link value INTB#
-  dw 0xdef8 ;; IRQ bitmap INTB# 
-  db 0x61 ;; link value INTC#
-  dw 0xdef8 ;; IRQ bitmap INTC# 
-  db 0x62 ;; link value INTD#
-  dw 0xdef8 ;; IRQ bitmap INTD#
-  db 3 ;; physical slot (0 = embedded)
-  db 0 ;; reserved
-  ;; 5th slot entry: 4rd PCI slot
-  db 0 ;; pci bus number
-  db 0x28 ;; pci device number (bit 7-3)
-  db 0x60 ;; link value INTA#
-  dw 0xdef8 ;; IRQ bitmap INTA# 
-  db 0x61 ;; link value INTB#
-  dw 0xdef8 ;; IRQ bitmap INTB# 
-  db 0x62 ;; link value INTC#
-  dw 0xdef8 ;; IRQ bitmap INTC# 
-  db 0x63 ;; link value INTD#
-  dw 0xdef8 ;; IRQ bitmap INTD#
-  db 4 ;; physical slot (0 = embedded)
-  db 0 ;; reserved
-  ;; 6th slot entry: 5rd PCI slot
-  db 0 ;; pci bus number
-  db 0x30 ;; pci device number (bit 7-3)
-  db 0x61 ;; link value INTA#
-  dw 0xdef8 ;; IRQ bitmap INTA# 
-  db 0x62 ;; link value INTB#
-  dw 0xdef8 ;; IRQ bitmap INTB# 
-  db 0x63 ;; link value INTC#
-  dw 0xdef8 ;; IRQ bitmap INTC# 
-  db 0x60 ;; link value INTD#
   dw 0xdef8 ;; IRQ bitmap INTD#
   db 5 ;; physical slot (0 = embedded)
   db 0 ;; reserved
diff -r b80f00215bba -r f555a90bcc37 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/ioemu/Makefile.target       Tue Nov 21 19:22:25 2006 +0000
@@ -298,7 +298,7 @@ ifeq ($(ARCH),ia64)
 ifeq ($(ARCH),ia64)
 LIBOBJS=helper2.o exec-dm.o i8259-dm.o
 else
-LIBOBJS=helper2.o exec-dm.o i8259-dm.o rtc-dm.o
+LIBOBJS=helper2.o exec-dm.o i8259-dm.o rtc-dm.o piix_pci-dm.o
 endif
 
 all: $(PROGS)
@@ -360,11 +360,11 @@ ifeq ($(TARGET_BASE_ARCH), i386)
 # Hardware support
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 ifeq ($(ARCH),ia64)
-VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
+VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o piix_pci.o
 else
 VL_OBJS+= fdc.o serial.o pc.o
 endif
-VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
+VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o
 VL_OBJS+= usb-uhci.o
 VL_OBJS+= piix4acpi.o
 VL_OBJS+= xenstore.o
diff -r b80f00215bba -r f555a90bcc37 tools/ioemu/target-i386-dm/i8259-dm.c
--- a/tools/ioemu/target-i386-dm/i8259-dm.c     Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/ioemu/target-i386-dm/i8259-dm.c     Tue Nov 21 19:22:25 2006 +0000
@@ -33,7 +33,7 @@ struct PicState2 {
 
 void pic_set_irq_new(void *opaque, int irq, int level)
 {
-    xc_hvm_set_irq_level(xc_handle, domid, irq, level);
+    xc_hvm_set_isa_irq_level(xc_handle, domid, irq, level);
 }
 
 /* obsolete function */
diff -r b80f00215bba -r f555a90bcc37 tools/libxc/xc_misc.c
--- a/tools/libxc/xc_misc.c     Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/libxc/xc_misc.c     Tue Nov 21 19:22:25 2006 +0000
@@ -90,19 +90,83 @@ int xc_perfc_control(int xc_handle,
     return rc;
 }
 
-int xc_hvm_set_irq_level(int xc_handle, domid_t dom, int irq, int level)
+int xc_hvm_set_pci_intx_level(
+    int xc_handle, domid_t dom,
+    uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
+    unsigned int level)
 {
     DECLARE_HYPERCALL;
-    struct xen_hvm_set_irq_level arg;
+    struct xen_hvm_set_pci_intx_level arg;
     int rc;
 
     hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_irq_level;
+    hypercall.arg[0] = HVMOP_set_pci_intx_level;
     hypercall.arg[1] = (unsigned long)&arg;
 
-    arg.domid = dom;
-    arg.irq   = irq;
-    arg.level = level;
+    arg.domid  = dom;
+    arg.domain = domain;
+    arg.bus    = bus;
+    arg.device = device;
+    arg.intx   = intx;
+    arg.level  = level;
+
+    if ( mlock(&arg, sizeof(arg)) != 0 )
+    {
+        PERROR("Could not lock memory");
+        return -1;
+    }
+
+    rc = do_xen_hypercall(xc_handle, &hypercall);
+
+    safe_munlock(&arg, sizeof(arg));
+
+    return rc;
+}
+
+int xc_hvm_set_isa_irq_level(
+    int xc_handle, domid_t dom,
+    uint8_t isa_irq,
+    unsigned int level)
+{
+    DECLARE_HYPERCALL;
+    struct xen_hvm_set_isa_irq_level arg;
+    int rc;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_set_isa_irq_level;
+    hypercall.arg[1] = (unsigned long)&arg;
+
+    arg.domid   = dom;
+    arg.isa_irq = isa_irq;
+    arg.level   = level;
+
+    if ( mlock(&arg, sizeof(arg)) != 0 )
+    {
+        PERROR("Could not lock memory");
+        return -1;
+    }
+
+    rc = do_xen_hypercall(xc_handle, &hypercall);
+
+    safe_munlock(&arg, sizeof(arg));
+
+    return rc;
+}
+
+int xc_hvm_set_pci_link_route(
+    int xc_handle, domid_t dom, uint8_t link, uint8_t isa_irq)
+{
+    DECLARE_HYPERCALL;
+    struct xen_hvm_set_pci_link_route arg;
+    int rc;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_set_pci_link_route;
+    hypercall.arg[1] = (unsigned long)&arg;
+
+    arg.domid   = dom;
+    arg.link    = link;
+    arg.isa_irq = isa_irq;
 
     if ( mlock(&arg, sizeof(arg)) != 0 )
     {
diff -r b80f00215bba -r f555a90bcc37 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Tue Nov 21 17:34:17 2006 +0000
+++ b/tools/libxc/xenctrl.h     Tue Nov 21 19:22:25 2006 +0000
@@ -666,6 +666,16 @@ evtchn_port_t xc_evtchn_pending(int xce_
  */
 int xc_evtchn_unmask(int xce_handle, evtchn_port_t port);
 
-int xc_hvm_set_irq_level(int xce_handle, domid_t dom, int irq, int level);
+int xc_hvm_set_pci_intx_level(
+    int xce_handle, domid_t dom,
+    uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
+    unsigned int level);
+int xc_hvm_set_isa_irq_level(
+    int xce_handle, domid_t dom,
+    uint8_t isa_irq,
+    unsigned int level);
+
+int xc_hvm_set_pci_link_route(
+    int xce_handle, domid_t dom, uint8_t link, uint8_t isa_irq);
 
 #endif
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/Makefile
--- a/xen/arch/x86/hvm/Makefile Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/Makefile Tue Nov 21 19:22:25 2006 +0000
@@ -4,11 +4,12 @@ obj-y += hvm.o
 obj-y += hvm.o
 obj-y += i8254.o
 obj-y += i8259.o
-obj-y += rtc.o
-obj-y += pmtimer.o
 obj-y += instrlen.o
 obj-y += intercept.o
 obj-y += io.o
+obj-y += irq.o
 obj-y += platform.o
+obj-y += pmtimer.o
+obj-y += rtc.o
 obj-y += vioapic.o
 obj-y += vlapic.o
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Tue Nov 21 19:22:25 2006 +0000
@@ -157,7 +157,6 @@ void hvm_do_resume(struct vcpu *v)
 
 int hvm_domain_initialise(struct domain *d)
 {
-    struct hvm_domain *platform = &d->arch.hvm_domain;
     int rc;
 
     if ( !hvm_enabled )
@@ -168,14 +167,13 @@ int hvm_domain_initialise(struct domain 
     }
 
     spin_lock_init(&d->arch.hvm_domain.pbuf_lock);
-    spin_lock_init(&d->arch.hvm_domain.round_robin_lock);
     spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
 
     rc = shadow_enable(d, SHM2_refcounts|SHM2_translate|SHM2_external);
     if ( rc != 0 )
         return rc;
 
-    pic_init(&platform->vpic, pic_irq_request, &platform->interrupt_request);
+    pic_init(domain_vpic(d));
     register_pic_io_hook(d);
 
     vioapic_init(d);
@@ -244,12 +242,6 @@ void hvm_vcpu_destroy(struct vcpu *v)
     /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
 }
 
-void pic_irq_request(void *data, int level)
-{
-    int *interrupt_request = data;
-    *interrupt_request = level;
-}
-
 int cpu_get_interrupt(struct vcpu *v, int *type)
 {
     int intno;
@@ -259,9 +251,9 @@ int cpu_get_interrupt(struct vcpu *v, in
     if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
         /* set irq request if a PIC irq is still pending */
         /* XXX: improve that */
-        spin_lock_irqsave(&vpic->lock, flags);
+        spin_lock_irqsave(vpic_lock(vpic), flags);
         pic_update_irq(vpic);
-        spin_unlock_irqrestore(&vpic->lock, flags);
+        spin_unlock_irqrestore(vpic_lock(vpic), flags);
         return intno;
     }
     /* read the irq from the PIC */
@@ -612,6 +604,124 @@ int hvm_bringup_ap(int vcpuid, int tramp
 
  out:
     xfree(ctxt);
+    return rc;
+}
+
+static int hvmop_set_pci_intx_level(
+    XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t) uop)
+{
+    struct xen_hvm_set_pci_intx_level op;
+    struct domain *d;
+    int rc;
+
+    if ( copy_from_guest(&op, uop, 1) )
+        return -EFAULT;
+
+    if ( !IS_PRIV(current->domain) )
+        return -EPERM;
+
+    if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) )
+        return -EINVAL;
+
+    d = find_domain_by_id(op.domid);
+    if ( d == NULL )
+        return -ESRCH;
+
+    rc = -EINVAL;
+    if ( !is_hvm_domain(d) )
+        goto out;
+
+    rc = 0;
+    switch ( op.level )
+    {
+    case 0:
+        hvm_pci_intx_deassert(d, op.device, op.intx);
+        break;
+    case 1:
+        hvm_pci_intx_assert(d, op.device, op.intx);
+        break;
+    default:
+        rc = -EINVAL;
+        break;
+    }
+
+ out:
+    put_domain(d);
+    return rc;
+}
+
+static int hvmop_set_isa_irq_level(
+    XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t) uop)
+{
+    struct xen_hvm_set_isa_irq_level op;
+    struct domain *d;
+    int rc;
+
+    if ( copy_from_guest(&op, uop, 1) )
+        return -EFAULT;
+
+    if ( !IS_PRIV(current->domain) )
+        return -EPERM;
+
+    if ( op.isa_irq > 15 )
+        return -EINVAL;
+
+    d = find_domain_by_id(op.domid);
+    if ( d == NULL )
+        return -ESRCH;
+
+    rc = -EINVAL;
+    if ( !is_hvm_domain(d) )
+        goto out;
+
+    rc = 0;
+    switch ( op.level )
+    {
+    case 0:
+        hvm_isa_irq_deassert(d, op.isa_irq);
+        break;
+    case 1:
+        hvm_isa_irq_assert(d, op.isa_irq);
+        break;
+    default:
+        rc = -EINVAL;
+        break;
+    }
+
+ out:
+    put_domain(d);
+    return rc;
+}
+
+static int hvmop_set_pci_link_route(
+    XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t) uop)
+{
+    struct xen_hvm_set_pci_link_route op;
+    struct domain *d;
+    int rc;
+
+    if ( copy_from_guest(&op, uop, 1) )
+        return -EFAULT;
+
+    if ( !IS_PRIV(current->domain) )
+        return -EPERM;
+
+    if ( (op.link > 3) || (op.isa_irq > 15) )
+        return -EINVAL;
+
+    d = find_domain_by_id(op.domid);
+    if ( d == NULL )
+        return -ESRCH;
+
+    rc = -EINVAL;
+    if ( !is_hvm_domain(d) )
+        goto out;
+
+    rc = 0;
+    hvm_set_pci_link_route(d, op.link, op.isa_irq);
+
+ out:
+    put_domain(d);
     return rc;
 }
 
@@ -687,6 +797,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
                     goto param_fail;
                 d->arch.hvm_domain.buffered_io_va = (unsigned long)p;
                 break;
+            case HVM_PARAM_CALLBACK_IRQ:
+                hvm_set_callback_gsi(d, a.value);
+                break;
             }
             d->arch.hvm_domain.params[a.index] = a.value;
             rc = 0;
@@ -702,31 +815,20 @@ long do_hvm_op(unsigned long op, XEN_GUE
         break;
     }
 
-    case HVMOP_set_irq_level:
-    {
-        struct xen_hvm_set_irq_level op;
-        struct domain *d;
-
-        if ( copy_from_guest(&op, arg, 1) )
-            return -EFAULT;
-
-        if ( !IS_PRIV(current->domain) )
-            return -EPERM;
-
-        d = find_domain_by_id(op.domid);
-        if ( d == NULL )
-            return -ESRCH;
-
-        rc = -EINVAL;
-        if ( is_hvm_domain(d) )
-        {
-            pic_set_irq(domain_vpic(d), op.irq, op.level);
-            rc = 0;
-        }
-
-        put_domain(d);
-        break;
-    }
+    case HVMOP_set_pci_intx_level:
+        rc = hvmop_set_pci_intx_level(
+            guest_handle_cast(arg, xen_hvm_set_pci_intx_level_t));
+        break;
+
+    case HVMOP_set_isa_irq_level:
+        rc = hvmop_set_isa_irq_level(
+            guest_handle_cast(arg, xen_hvm_set_isa_irq_level_t));
+        break;
+
+    case HVMOP_set_pci_link_route:
+        rc = hvmop_set_pci_link_route(
+            guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
+        break;
 
     default:
     {
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/i8259.c
--- a/xen/arch/x86/hvm/i8259.c  Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/i8259.c  Tue Nov 21 19:22:25 2006 +0000
@@ -42,7 +42,7 @@ static inline void pic_set_irq1(PicState
 {
     int mask;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     mask = 1 << irq;
     if (s->elcr & mask) {
@@ -72,7 +72,7 @@ static inline int get_priority(PicState 
 {
     int priority;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     if (mask == 0)
         return 8;
@@ -87,9 +87,9 @@ static int pic_get_irq(PicState *s)
 {
     int mask, cur_priority, priority;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
-
-    mask = (s->irr|s->irr_xen) & ~s->imr;
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
+
+    mask = s->irr & ~s->imr;
     priority = get_priority(s, mask);
     if (priority == 8)
         return -1;
@@ -115,7 +115,7 @@ void pic_update_irq(struct vpic *vpic)
 {
     int irq2, irq;
 
-    ASSERT(spin_is_locked(&vpic->lock));
+    ASSERT(spin_is_locked(vpic_lock(vpic)));
 
     /* first look at slave pic */
     irq2 = pic_get_irq(&vpic->pics[1]);
@@ -126,56 +126,21 @@ void pic_update_irq(struct vpic *vpic)
     }
     /* look at requested irq */
     irq = pic_get_irq(&vpic->pics[0]);
-    if (irq >= 0) {
-        vpic->irq_request(vpic->irq_request_opaque, 1);
-    }
-}
-
-void pic_set_xen_irq(void *opaque, int irq, int level)
-{
-    struct vpic *vpic = opaque;
-    unsigned long flags;
-    PicState *ps;
-
-    spin_lock_irqsave(&vpic->lock, flags);
-
-    vioapic_set_xen_irq(current->domain, irq, level);
-
-    /* Set it on the 8259s */
-    ps = &vpic->pics[irq >> 3];
-    if (!(ps->elcr & (1 << (irq & 7))))
-       gdprintk(XENLOG_WARNING, "edge-triggered override IRQ?\n");
-    if (level) {
-       ps->irr_xen |= 1 << (irq & 7);
-    } else {
-       ps->irr_xen &= ~(1 << (irq & 7));
-    }
-
+    if (irq >= 0)
+        vpic->irq_pending = 1;
+}
+
+void pic_set_irq(struct vpic *vpic, int irq, int level)
+{
+    ASSERT(spin_is_locked(vpic_lock(vpic)));
+    pic_set_irq1(&vpic->pics[irq >> 3], irq & 7, level);
     pic_update_irq(vpic);
-    spin_unlock_irqrestore(&vpic->lock, flags);
-}
-
-void pic_set_irq(struct vpic *vpic, int irq, int level)
-{
-    unsigned long flags;
-
-    if ( irq < 0 )
-        return;
-
-    spin_lock_irqsave(&vpic->lock, flags);
-    vioapic_set_irq(vpic_domain(vpic), irq, level);
-    if ( irq < 16 )
-    {
-        pic_set_irq1(&vpic->pics[irq >> 3], irq & 7, level);
-        pic_update_irq(vpic);
-    }
-    spin_unlock_irqrestore(&vpic->lock, flags);
 }
 
 /* acknowledge interrupt 'irq' */
 static inline void pic_intack(PicState *s, int irq)
 {
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     if (s->auto_eoi) {
         if (s->rotate_on_auto_eoi)
@@ -193,7 +158,7 @@ static int pic_read_irq(struct vpic *vpi
     int irq, irq2, intno;
     unsigned long flags;
 
-    spin_lock_irqsave(&vpic->lock, flags);
+    spin_lock_irqsave(vpic_lock(vpic), flags);
     irq = pic_get_irq(&vpic->pics[0]);
     if (irq >= 0) {
         pic_intack(&vpic->pics[0], irq);
@@ -218,7 +183,7 @@ static int pic_read_irq(struct vpic *vpi
        gdprintk(XENLOG_WARNING, "Spurious irq on master i8259.\n");
     }
     pic_update_irq(vpic);
-    spin_unlock_irqrestore(&vpic->lock, flags);
+    spin_unlock_irqrestore(vpic_lock(vpic), flags);
 
     return intno;
 }
@@ -227,7 +192,7 @@ static void pic_reset(void *opaque)
 {
     PicState *s = opaque;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     s->last_irr = 0;
     s->irr = 0;
@@ -251,7 +216,7 @@ static void pic_ioport_write(void *opaqu
     PicState *s = opaque;
     int priority, cmd, irq;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     addr &= 1;
     if (addr == 0) {
@@ -259,7 +224,7 @@ static void pic_ioport_write(void *opaqu
             /* init */
             pic_reset(s);
             /* deassert a pending interrupt */
-            s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
+            s->pics_state->irq_pending = 0;
             s->init_state = 1;
             s->init4 = val & 1;
             if (val & 0x02)
@@ -342,7 +307,7 @@ static uint32_t pic_poll_read (PicState 
 {
     int ret;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     ret = pic_get_irq(s);
     if (ret >= 0) {
@@ -351,7 +316,6 @@ static uint32_t pic_poll_read (PicState 
             s->pics_state->pics[0].irr &= ~(1 << 2);
         }
         s->irr &= ~(1 << ret);
-        s->irr_xen &= ~(1 << ret);
         s->isr &= ~(1 << ret);
         if (addr1 >> 7 || ret != 2)
             pic_update_irq(s->pics_state);
@@ -369,7 +333,7 @@ static uint32_t pic_ioport_read(void *op
     unsigned int addr;
     int ret;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     addr = addr1;
     addr &= 1;
@@ -381,7 +345,7 @@ static uint32_t pic_ioport_read(void *op
             if (s->read_reg_select)
                 ret = s->isr;
             else
-                ret = s->irr | s->irr_xen;
+                ret = s->irr;
         } else {
             ret = s->imr;
         }
@@ -393,7 +357,7 @@ static void elcr_ioport_write(void *opaq
 {
     PicState *s = opaque;
 
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     s->elcr = val & s->elcr_mask;
 }
@@ -407,7 +371,7 @@ static uint32_t elcr_ioport_read(void *o
 /* XXX: add generic master/slave system */
 static void pic_init1(int io_addr, int elcr_addr, PicState *s)
 {
-    ASSERT(spin_is_locked(&s->pics_state->lock));
+    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
 
     pic_reset(s);
 
@@ -416,23 +380,20 @@ static void pic_init1(int io_addr, int e
     s->elcr = 0xff & s->elcr_mask;
 }
 
-void pic_init(struct vpic *vpic, void (*irq_request)(void *, int),
-              void *irq_request_opaque)
+void pic_init(struct vpic *vpic)
 {
     unsigned long flags;
 
     memset(vpic, 0, sizeof(*vpic));
-    spin_lock_init(&vpic->lock);
+    spin_lock_init(vpic_lock(vpic));
     vpic->pics[0].pics_state = vpic;
     vpic->pics[1].pics_state = vpic;
     vpic->pics[0].elcr_mask = 0xf8;
     vpic->pics[1].elcr_mask = 0xde;
-    spin_lock_irqsave(&vpic->lock, flags);
+    spin_lock_irqsave(vpic_lock(vpic), flags);
     pic_init1(0x20, 0x4d0, &vpic->pics[0]);
     pic_init1(0xa0, 0x4d1, &vpic->pics[1]);
-    spin_unlock_irqrestore(&vpic->lock, flags);
-    vpic->irq_request = irq_request;
-    vpic->irq_request_opaque = irq_request_opaque;
+    spin_unlock_irqrestore(vpic_lock(vpic), flags);
 }
 
 static int intercept_pic_io(ioreq_t *p)
@@ -452,16 +413,16 @@ static int intercept_pic_io(ioreq_t *p)
             (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
         else
             data = p->data;
-        spin_lock_irqsave(&pic->lock, flags);
+        spin_lock_irqsave(vpic_lock(pic), flags);
         pic_ioport_write((void*)&pic->pics[p->addr>>7],
                 (uint32_t) p->addr, (uint32_t) (data & 0xff));
-        spin_unlock_irqrestore(&pic->lock, flags);
+        spin_unlock_irqrestore(vpic_lock(pic), flags);
     }
     else {
-        spin_lock_irqsave(&pic->lock, flags);
+        spin_lock_irqsave(vpic_lock(pic), flags);
         data = pic_ioport_read(
             (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
-        spin_unlock_irqrestore(&pic->lock, flags);
+        spin_unlock_irqrestore(vpic_lock(pic), flags);
         if ( p->data_is_ptr )
             (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
         else
@@ -487,10 +448,10 @@ static int intercept_elcr_io(ioreq_t *p)
             (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
         else
             data = p->data;
-        spin_lock_irqsave(&vpic->lock, flags);
+        spin_lock_irqsave(vpic_lock(vpic), flags);
         elcr_ioport_write((void*)&vpic->pics[p->addr&1],
                 (uint32_t) p->addr, (uint32_t)( data & 0xff));
-        spin_unlock_irqrestore(&vpic->lock, flags);
+        spin_unlock_irqrestore(vpic_lock(vpic), flags);
     }
     else {
         data = (u64) elcr_ioport_read(
@@ -522,7 +483,7 @@ int cpu_get_pic_interrupt(struct vcpu *v
     if ( !vlapic_accept_pic_intr(v) )
         return -1;
 
-    if (cmpxchg(&plat->interrupt_request, 1, 0) != 1)
+    if ( xchg(&plat->irq.vpic.irq_pending, 0) == 0 )
         return -1;
 
     /* read the irq from the PIC */
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/rtc.c    Tue Nov 21 19:22:25 2006 +0000
@@ -34,12 +34,10 @@ void rtc_pie_callback(void *opaque)
 void rtc_pie_callback(void *opaque)
 {
     RTCState *s = opaque;
-    struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain;
-    struct vpic       *pic  = &plat->vpic;
     /* Record that we have fired */
     s->cmos_data[RTC_REG_C] |= (RTC_IRQF|RTC_PF); /* 0xc0 */
     /* Fire */
-    pic_set_irq(pic, s->irq, 1);
+    hvm_isa_irq_assert(s->vcpu->domain, s->irq);
     /* Remember to fire again */
     s->next_pie = NOW() + s->period;
     set_timer(&s->pie_timer, s->next_pie);
@@ -53,8 +51,9 @@ static void rtc_timer_update(RTCState *s
     int period;
 
     period_code = s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
-    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & RTC_PIE)) {
-        if (period_code <= 2)
+    if ( (period_code != 0) && (s->cmos_data[RTC_REG_B] & RTC_PIE) )
+    {
+        if ( period_code <= 2 )
             period_code += 7;
         
         period = 1 << (period_code - 1); /* period in 32 Khz cycles */
@@ -65,7 +64,9 @@ static void rtc_timer_update(RTCState *s
 #endif
         s->next_pie = NOW() + s->period;
         set_timer(&s->pie_timer, s->next_pie);
-    } else {
+    }
+    else
+    {
         stop_timer(&s->pie_timer);
     }
 }
@@ -76,80 +77,84 @@ static int rtc_ioport_write(void *opaque
 {
     RTCState *s = opaque;
 
-    if ((addr & 1) == 0) {
+    if ( (addr & 1) == 0 )
+    {
         s->cmos_index = data & 0x7f;
-        if (s->cmos_index < RTC_SIZE)
-            return 1;
-    } else if (s->cmos_index < RTC_SIZE) {
+        return (s->cmos_index < RTC_SIZE);
+    }
+
+    if (s->cmos_index >= RTC_SIZE)
+        return 0;
+
 #ifdef DEBUG_RTC
-        printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
-               s->cmos_index, data);
-#endif        
-        switch(s->cmos_index) {
-        case RTC_SECONDS_ALARM:
-        case RTC_MINUTES_ALARM:
-        case RTC_HOURS_ALARM:
-            s->cmos_data[s->cmos_index] = data;
-            break;
-        case RTC_SECONDS:
-        case RTC_MINUTES:
-        case RTC_HOURS:
-        case RTC_DAY_OF_WEEK:
-        case RTC_DAY_OF_MONTH:
-        case RTC_MONTH:
-        case RTC_YEAR:
-            s->cmos_data[s->cmos_index] = data;
-            /* if in set mode, do not update the time */
-            if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+    printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
+           s->cmos_index, data);
+#endif
+
+    switch ( s->cmos_index )
+    {
+    case RTC_SECONDS_ALARM:
+    case RTC_MINUTES_ALARM:
+    case RTC_HOURS_ALARM:
+        s->cmos_data[s->cmos_index] = data;
+        break;
+    case RTC_SECONDS:
+    case RTC_MINUTES:
+    case RTC_HOURS:
+    case RTC_DAY_OF_WEEK:
+    case RTC_DAY_OF_MONTH:
+    case RTC_MONTH:
+    case RTC_YEAR:
+        s->cmos_data[s->cmos_index] = data;
+        /* if in set mode, do not update the time */
+        if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
+            rtc_set_time(s);
+        break;
+    case RTC_REG_A:
+        /* UIP bit is read only */
+        s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
+            (s->cmos_data[RTC_REG_A] & RTC_UIP);
+        rtc_timer_update(s);
+        break;
+    case RTC_REG_B:
+        if ( data & RTC_SET )
+        {
+            /* set mode: reset UIP mode */
+            s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
+            data &= ~RTC_UIE;
+        }
+        else
+        {
+            /* if disabling set mode, update the time */
+            if ( s->cmos_data[RTC_REG_B] & RTC_SET )
                 rtc_set_time(s);
-            }
-            break;
-        case RTC_REG_A:
-            /* UIP bit is read only */
-            s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
-                (s->cmos_data[RTC_REG_A] & RTC_UIP);
-            rtc_timer_update(s);
-            break;
-        case RTC_REG_B:
-            if (data & RTC_SET) {
-                /* set mode: reset UIP mode */
-                s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
-                data &= ~RTC_UIE;
-            } else {
-                /* if disabling set mode, update the time */
-                if (s->cmos_data[RTC_REG_B] & RTC_SET) {
-                    rtc_set_time(s);
-                }
-            }
-            s->cmos_data[RTC_REG_B] = data;
-            rtc_timer_update(s);
-            break;
-        case RTC_REG_C:
-        case RTC_REG_D:
-            /* cannot write to them */
-            break;
         }
-        return 1;
-    }
-    return 0;
+        s->cmos_data[RTC_REG_B] = data;
+        rtc_timer_update(s);
+        break;
+    case RTC_REG_C:
+    case RTC_REG_D:
+        /* cannot write to them */
+        break;
+    }
+
+    return 1;
 }
 
 static inline int to_bcd(RTCState *s, int a)
 {
-    if (s->cmos_data[RTC_REG_B] & 0x04) {
+    if ( s->cmos_data[RTC_REG_B] & 0x04 )
         return a;
-    } else {
+    else
         return ((a / 10) << 4) | (a % 10);
-    }
 }
 
 static inline int from_bcd(RTCState *s, int a)
 {
-    if (s->cmos_data[RTC_REG_B] & 0x04) {
+    if ( s->cmos_data[RTC_REG_B] & 0x04 )
         return a;
-    } else {
+    else
         return ((a >> 4) * 10) + (a & 0x0f);
-    }
 }
 
 static void rtc_set_time(RTCState *s)
@@ -159,10 +164,9 @@ static void rtc_set_time(RTCState *s)
     tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
     tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
     tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
-    if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
-        (s->cmos_data[RTC_HOURS] & 0x80)) {
+    if ( !(s->cmos_data[RTC_REG_B] & 0x02) &&
+         (s->cmos_data[RTC_HOURS] & 0x80) )
         tm->tm_hour += 12;
-    }
     tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
     tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
     tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
@@ -175,13 +179,16 @@ static void rtc_copy_date(RTCState *s)
 
     s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
     s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
-    if (s->cmos_data[RTC_REG_B] & RTC_24H) {
+    if ( s->cmos_data[RTC_REG_B] & RTC_24H )
+    {
         /* 24 hour format */
         s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
-    } else {
+    }
+    else
+    {
         /* 12 hour format */
         s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
-        if (tm->tm_hour >= 12)
+        if ( tm->tm_hour >= 12 )
             s->cmos_data[RTC_HOURS] |= 0x80;
     }
     s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
@@ -197,13 +204,12 @@ static int get_days_in_month(int month, 
         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
     };
     int d;
-    if ((unsigned )month >= 12)
+    if ( (unsigned)month >= 12 )
         return 31;
     d = days_tab[month];
-    if (month == 1) {
-        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
+    if ( month == 1 )
+        if ( (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) )
             d++;
-    }
     return d;
 }
 
@@ -248,16 +254,18 @@ static void rtc_update_second(void *opaq
     RTCState *s = opaque;
 
     /* if the oscillator is not in normal operation, we do not update */
-    if ((s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ) {
+    if ( (s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
+    {
         s->next_second_time += 1000000000ULL;
         set_timer(&s->second_timer, s->next_second_time);
-    } else {
+    }
+    else
+    {
         rtc_next_second(&s->current_tm);
         
-        if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
-            /* update in progress bit */
+        if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
             s->cmos_data[RTC_REG_A] |= RTC_UIP;
-        }
+
         /* Delay time before update cycle */
         set_timer(&s->second_timer2, s->next_second_time + 244000);
     }
@@ -266,33 +274,32 @@ static void rtc_update_second2(void *opa
 static void rtc_update_second2(void *opaque)
 {
     RTCState *s = opaque;
-    struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain;
-    struct vpic       *pic  = &plat->vpic;
-
-    if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+
+    if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
         rtc_copy_date(s);
-    }
 
     /* check alarm */
-    if (s->cmos_data[RTC_REG_B] & RTC_AIE) {
-        if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
-             s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
-            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
-             s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
-            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
-             s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
-
+    if ( s->cmos_data[RTC_REG_B] & RTC_AIE )
+    {
+        if ( ((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
+              s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
+             ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
+              s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
+             ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
+              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour) )
+        {
             s->cmos_data[RTC_REG_C] |= 0xa0; 
-            pic_set_irq(pic, s->irq, 0);
-            pic_set_irq(pic, s->irq, 1);
+            hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+            hvm_isa_irq_assert(s->vcpu->domain, s->irq);
         }
     }
 
     /* update ended interrupt */
-    if (s->cmos_data[RTC_REG_B] & RTC_UIE) {
+    if ( s->cmos_data[RTC_REG_B] & RTC_UIE )
+    {
         s->cmos_data[RTC_REG_C] |= 0x90; 
-        pic_set_irq(pic, s->irq, 0);
-        pic_set_irq(pic, s->irq, 1);
+        hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+        hvm_isa_irq_assert(s->vcpu->domain, s->irq);
     }
 
     /* clear update in progress bit */
@@ -305,41 +312,41 @@ static uint32_t rtc_ioport_read(void *op
 static uint32_t rtc_ioport_read(void *opaque, uint32_t addr)
 {
     RTCState *s = opaque;
-    struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain;
-    struct vpic       *pic  = &plat->vpic;
     int ret;
 
-    if ((addr & 1) == 0) {
+    if ( (addr & 1) == 0 )
         return 0xff;
-    } else {
-        switch(s->cmos_index) {
-        case RTC_SECONDS:
-        case RTC_MINUTES:
-        case RTC_HOURS:
-        case RTC_DAY_OF_WEEK:
-        case RTC_DAY_OF_MONTH:
-        case RTC_MONTH:
-        case RTC_YEAR:
-            ret = s->cmos_data[s->cmos_index];
-            break;
-        case RTC_REG_A:
-            ret = s->cmos_data[s->cmos_index];
-            break;
-        case RTC_REG_C:
-            ret = s->cmos_data[s->cmos_index];
-            pic_set_irq(pic, s->irq, 0);
-            s->cmos_data[RTC_REG_C] = 0x00; 
-            break;
-        default:
-            ret = s->cmos_data[s->cmos_index];
-            break;
-        }
+
+    switch ( s->cmos_index )
+    {
+    case RTC_SECONDS:
+    case RTC_MINUTES:
+    case RTC_HOURS:
+    case RTC_DAY_OF_WEEK:
+    case RTC_DAY_OF_MONTH:
+    case RTC_MONTH:
+    case RTC_YEAR:
+        ret = s->cmos_data[s->cmos_index];
+        break;
+    case RTC_REG_A:
+        ret = s->cmos_data[s->cmos_index];
+        break;
+    case RTC_REG_C:
+        ret = s->cmos_data[s->cmos_index];
+        hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+        s->cmos_data[RTC_REG_C] = 0x00; 
+        break;
+    default:
+        ret = s->cmos_data[s->cmos_index];
+        break;
+    }
+
 #ifdef DEBUG_RTC
-        printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
-               s->cmos_index, ret);
+    printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
+           s->cmos_index, ret);
 #endif
-        return ret;
-    }
+
+    return ret;
 }
 
 static int handle_rtc_io(ioreq_t *p)
@@ -347,20 +354,23 @@ static int handle_rtc_io(ioreq_t *p)
     struct vcpu *v = current;
     struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
 
-    if (p->size != 1 ||
-        p->data_is_ptr ||
-        p->type != IOREQ_TYPE_PIO){
+    if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+    {
         printk("HVM_RTC: wrong RTC IO!\n");
         return 1;
     }
     
-    if (p->dir == 0) { /* write */
-        if (rtc_ioport_write(vrtc, p->addr, p->data & 0xFF))
+    if ( p->dir == 0 ) /* write */
+    {
+        if ( rtc_ioport_write(vrtc, p->addr, p->data & 0xFF) )
             return 1;
-    } else if (p->dir == 1 && vrtc->cmos_index < RTC_SIZE) { /* read */
+    }
+    else if ( (p->dir == 1) && (vrtc->cmos_index < RTC_SIZE) ) /* read */
+    {
         p->data = rtc_ioport_read(vrtc, p->addr);
         return 1;
     }
+
     return 0;
 }
 
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/svm/intr.c       Tue Nov 21 19:22:25 2006 +0000
@@ -65,8 +65,6 @@ asmlinkage void svm_intr_assist(void)
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     struct hvm_domain *plat=&v->domain->arch.hvm_domain;
     struct periodic_time *pt = &plat->pl_time.periodic_tm;
-    struct vpic *pic= &plat->vpic;
-    int callback_irq;
     int intr_type = APIC_DM_EXTINT;
     int intr_vector = -1;
     int re_injecting = 0;
@@ -119,18 +117,11 @@ asmlinkage void svm_intr_assist(void)
     {
         if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
         {
-            pic_set_irq(pic, pt->irq, 0);
-            pic_set_irq(pic, pt->irq, 1);
+            hvm_isa_irq_deassert(current->domain, pt->irq);
+            hvm_isa_irq_assert(current->domain, pt->irq);
         }
 
-        if ( v->vcpu_id == 0 )
-        {
-            callback_irq =
-                v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
-            if ( callback_irq != 0 )
-                pic_set_xen_irq(pic, callback_irq,
-                                local_events_need_delivery());
-        }
+        hvm_set_callback_irq_level();
 
         if ( cpu_has_pending_irq(v) )
             intr_vector = cpu_get_interrupt(v, &intr_type);
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/vioapic.c        Tue Nov 21 19:22:25 2006 +0000
@@ -42,13 +42,12 @@
 
 /* HACK: Route IRQ0 only to VCPU0 to prevent time jumps. */
 #define IRQ0_SPECIAL_ROUTING 1
-#ifdef IRQ0_SPECIAL_ROUTING
-static int redir_warning_done = 0; 
-#endif
 
 #if defined(__ia64__)
 #define opt_hvm_debug_level opt_vmx_debug_level
 #endif
+
+static void vioapic_deliver(struct vioapic *vioapic, int irq);
 
 static unsigned long vioapic_read_indirect(struct vioapic *vioapic,
                                            unsigned long addr,
@@ -122,19 +121,48 @@ static unsigned long vioapic_read(struct
     return result;
 }
 
-static void vioapic_update_imr(struct vioapic *vioapic, int index)
-{
-    if ( vioapic->redirtbl[index].fields.mask )
-        set_bit(index, &vioapic->imr);
+static void vioapic_write_redirent(
+    struct vioapic *vioapic, unsigned int idx, int top_word, uint32_t val)
+{
+    struct domain *d = vioapic_domain(vioapic);
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    union vioapic_redir_entry *pent, ent;
+
+    spin_lock(&hvm_irq->lock);
+
+    pent = &vioapic->redirtbl[idx];
+    ent  = *pent;
+
+    if ( top_word )
+    {
+        /* Contains only the dest_id. */
+        ent.bits = (uint32_t)ent.bits | ((uint64_t)val << 32);
+    }
     else
-        clear_bit(index, &vioapic->imr);
-}
-
-
-static void vioapic_write_indirect(struct vioapic *vioapic,
-                                   unsigned long addr,
-                                   unsigned long length,
-                                   unsigned long val)
+    {
+        /* Remote IRR and Delivery Status are read-only. */
+        ent.bits = ((ent.bits >> 32) << 32) | val;
+        ent.fields.delivery_status = 0;
+        ent.fields.remote_irr = pent->fields.remote_irr;
+    }
+
+    *pent = ent;
+
+    if ( (ent.fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
+         !ent.fields.mask &&
+         !ent.fields.remote_irr &&
+         hvm_irq->gsi_assert_count[idx] )
+    {
+        pent->fields.remote_irr = 1;
+        vioapic_deliver(vioapic, idx);
+    }
+
+    spin_unlock(&hvm_irq->lock);
+}
+
+static void vioapic_write_indirect(
+    struct vioapic *vioapic, unsigned long addr,
+    unsigned long length, unsigned long val)
 {
     switch ( vioapic->ioregsel )
     {
@@ -154,7 +182,6 @@ static void vioapic_write_indirect(struc
     default:
     {
         uint32_t redir_index = (vioapic->ioregsel - 0x10) >> 1;
-        uint64_t redir_content;
 
         HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_write_indirect "
                     "change redir index %x val %lx\n",
@@ -167,38 +194,11 @@ static void vioapic_write_indirect(struc
             break;
         }
 
-        redir_content = vioapic->redirtbl[redir_index].bits;
-
-        if ( vioapic->ioregsel & 0x1 )
-        {
-#ifdef IRQ0_SPECIAL_ROUTING
-            if ( !redir_warning_done && (redir_index == 0) &&
-                 ((val >> 24) != 0) )
-            {
-                /*
-                 * Cannot yet handle delivering PIT interrupts to any VCPU != 
-                 * 0. Needs proper fixing, but for now simply spit a warning 
-                 * that we're going to ignore the target in practice and always
-                 * deliver to VCPU 0.
-                 */
-                printk("IO-APIC: PIT (IRQ0) redirect to VCPU %lx "
-                       "will be ignored.\n", val >> 24); 
-                redir_warning_done = 1;
-            }
-#endif
-            redir_content = (((uint64_t)val & 0xffffffff) << 32) |
-                (redir_content & 0xffffffff);
-        }
-        else
-        {
-            redir_content = ((redir_content >> 32) << 32) |
-                (val & 0xffffffff);
-        }
-        vioapic->redirtbl[redir_index].bits = redir_content;
-        vioapic_update_imr(vioapic, redir_index);
-        break;
-    }
-    } /* switch */
+        vioapic_write_redirent(
+            vioapic, redir_index, vioapic->ioregsel&1, val);
+        break;
+    }
+    }
 }
 
 static void vioapic_write(struct vcpu *v,
@@ -245,27 +245,13 @@ struct hvm_mmio_handler vioapic_mmio_han
     .write_handler = vioapic_write
 };
 
-static void vioapic_reset(struct vioapic *vioapic)
-{
-    int i;
-
-    memset(vioapic, 0, sizeof(*vioapic));
-
-    for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
-    {
-        vioapic->redirtbl[i].fields.mask = 0x1;
-        vioapic_update_imr(vioapic, i);
-    }
-}
-
-static int ioapic_inj_irq(struct vioapic *vioapic,
-                          struct vlapic * target,
-                          uint8_t vector,
-                          uint8_t trig_mode,
-                          uint8_t delivery_mode)
-{
-    int result = 0;
-
+static void ioapic_inj_irq(
+    struct vioapic *vioapic,
+    struct vlapic *target,
+    uint8_t vector,
+    uint8_t trig_mode,
+    uint8_t delivery_mode)
+{
     HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
                 "irq %d trig %d delive mode %d\n",
                 vector, trig_mode, delivery_mode);
@@ -274,30 +260,23 @@ static int ioapic_inj_irq(struct vioapic
     {
     case dest_Fixed:
     case dest_LowestPrio:
-        if ( vlapic_set_irq(target, vector, trig_mode) && (trig_mode == 1) )
-            gdprintk(XENLOG_WARNING, "level interrupt before cleared\n");
-        result = 1;
+        if ( vlapic_set_irq(target, vector, trig_mode) )
+            vcpu_kick(vlapic_vcpu(target));
         break;
     default:
         gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
         break;
     }
-
-    return result;
-}
-
-static uint32_t ioapic_get_delivery_bitmask(struct vioapic *vioapic,
-                                            uint16_t dest,
-                                            uint8_t dest_mode,
-                                            uint8_t vector,
-                                            uint8_t delivery_mode)
+}
+
+static uint32_t ioapic_get_delivery_bitmask(
+    struct vioapic *vioapic, uint16_t dest, uint8_t dest_mode)
 {
     uint32_t mask = 0;
     struct vcpu *v;
 
     HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
-                "dest %d dest_mode %d vector %d del_mode %d\n",
-                dest, dest_mode, vector, delivery_mode);
+                "dest %d dest_mode %d\n", dest, dest_mode);
 
     if ( dest_mode == 0 ) /* Physical mode. */
     {
@@ -325,12 +304,12 @@ static uint32_t ioapic_get_delivery_bitm
     }
 
  out:
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
-                "mask %x\n", mask);
+    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask mask %x\n",
+                mask);
     return mask;
 }
 
-static void ioapic_deliver(struct vioapic *vioapic, int irq)
+static void vioapic_deliver(struct vioapic *vioapic, int irq)
 {
     uint16_t dest = vioapic->redirtbl[irq].fields.dest_id;
     uint8_t dest_mode = vioapic->redirtbl[irq].fields.dest_mode;
@@ -341,13 +320,14 @@ static void ioapic_deliver(struct vioapi
     struct vlapic *target;
     struct vcpu *v;
 
+    ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq.lock));
+
     HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
                 "dest=%x dest_mode=%x delivery_mode=%x "
                 "vector=%x trig_mode=%x\n",
                 dest, dest_mode, delivery_mode, vector, trig_mode);
 
-    deliver_bitmask = ioapic_get_delivery_bitmask(
-        vioapic, dest, dest_mode, vector, delivery_mode);
+    deliver_bitmask = ioapic_get_delivery_bitmask(vioapic, dest, dest_mode);
     if ( !deliver_bitmask )
     {
         HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
@@ -373,7 +353,6 @@ static void ioapic_deliver(struct vioapi
         if ( target != NULL )
         {
             ioapic_inj_irq(vioapic, target, vector, trig_mode, delivery_mode);
-            vcpu_kick(vlapic_vcpu(target));
         }
         else
         {
@@ -405,7 +384,6 @@ static void ioapic_deliver(struct vioapi
                 target = vcpu_vlapic(v);
                 ioapic_inj_irq(vioapic, target, vector,
                                trig_mode, delivery_mode);
-                vcpu_kick(vlapic_vcpu(target));
             }
         }
         break;
@@ -422,98 +400,32 @@ static void ioapic_deliver(struct vioapi
     }
 }
 
-static int ioapic_get_highest_irq(struct vioapic *vioapic)
-{
-    uint32_t irqs = vioapic->irr | vioapic->irr_xen;
-    irqs &= ~vioapic->isr & ~vioapic->imr;
-    return fls(irqs) - 1;
-}
-
-static void service_ioapic(struct vioapic *vioapic)
-{
-    int irq;
-
-    while ( (irq = ioapic_get_highest_irq(vioapic)) != -1 )
-    {
-        HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic highest irq %x\n", irq);
-
-        if ( !test_bit(irq, &vioapic->imr) )
-            ioapic_deliver(vioapic, irq);
-
-        if ( vioapic->redirtbl[irq].fields.trig_mode == VIOAPIC_LEVEL_TRIG )
-            vioapic->isr |= (1 << irq);
-
-        vioapic->irr     &= ~(1 << irq);
-        vioapic->irr_xen &= ~(1 << irq);
-    }
-}
-
-void vioapic_set_xen_irq(struct domain *d, int irq, int level)
+void vioapic_irq_positive_edge(struct domain *d, unsigned int irq)
 {
     struct vioapic *vioapic = domain_vioapic(d);
-
-    if ( vioapic->redirtbl[irq].fields.mask )
+    union vioapic_redir_entry *ent;
+
+    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_irq_positive_edge irq %x", irq);
+
+    ASSERT(irq < VIOAPIC_NUM_PINS);
+    ASSERT(spin_is_locked(&d->arch.hvm_domain.irq.lock));
+
+    ent = &vioapic->redirtbl[irq];
+    if ( ent->fields.mask )
         return;
 
-    if ( vioapic->redirtbl[irq].fields.trig_mode == VIOAPIC_EDGE_TRIG )
-        gdprintk(XENLOG_WARNING, "Forcing edge triggered APIC irq %d?\n", irq);
-
-    if ( level )
-        vioapic->irr_xen |= 1 << irq;
-    else
-        vioapic->irr_xen &= ~(1 << irq);
-
-    service_ioapic(vioapic);
-}
-
-void vioapic_set_irq(struct domain *d, int irq, int level)
-{
-    struct vioapic *vioapic = domain_vioapic(d);
-    uint32_t bit;
-
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq irq %x level %x", 
-                irq, level);
-
-    if ( (irq < 0) || (irq >= VIOAPIC_NUM_PINS) )
-        return;
-
-    if ( vioapic->redirtbl[irq].fields.mask )
-        return;
-
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_set_irq entry %x "
-                "vector %x delivery_mode %x dest_mode %x delivery_status %x "
-                "polarity %x remote_irr %x trig_mode %x mask %x dest_id %x\n",
-                irq,
-                vioapic->redirtbl[irq].fields.vector,
-                vioapic->redirtbl[irq].fields.delivery_mode,
-                vioapic->redirtbl[irq].fields.dest_mode,
-                vioapic->redirtbl[irq].fields.delivery_status,
-                vioapic->redirtbl[irq].fields.polarity,
-                vioapic->redirtbl[irq].fields.remote_irr,
-                vioapic->redirtbl[irq].fields.trig_mode,
-                vioapic->redirtbl[irq].fields.mask,
-                vioapic->redirtbl[irq].fields.dest_id);
-
-    bit = 1 << irq;
-    if ( vioapic->redirtbl[irq].fields.trig_mode == VIOAPIC_LEVEL_TRIG )
-    {
-        if ( level )
-            vioapic->irr |= bit;
-        else
-            vioapic->irr &= ~bit;
-    }
-    else
-    {
-        if ( level )
-            /* XXX No irr clear for edge interrupt */
-            vioapic->irr |= bit;
-    }
-
-    service_ioapic(vioapic);
-}
-
-/* XXX If level interrupt, use vector->irq table for performance */
-static int get_redir_num(struct vioapic *vioapic, int vector)
+    if ( ent->fields.trig_mode == VIOAPIC_EDGE_TRIG )
+    {
+        vioapic_deliver(vioapic, irq);
+    }
+    else if ( !ent->fields.remote_irr )
+    {
+        ent->fields.remote_irr = 1;
+        vioapic_deliver(vioapic, irq);
+    }
+}
+
+static int get_eoi_gsi(struct vioapic *vioapic, int vector)
 {
     int i;
 
@@ -527,29 +439,40 @@ void vioapic_update_EOI(struct domain *d
 void vioapic_update_EOI(struct domain *d, int vector)
 {
     struct vioapic *vioapic = domain_vioapic(d);
-    int redir_num;
-
-    if ( (redir_num = get_redir_num(vioapic, vector)) == -1 )
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    union vioapic_redir_entry *ent;
+    int gsi;
+
+    spin_lock(&hvm_irq->lock);
+
+    if ( (gsi = get_eoi_gsi(vioapic, vector)) == -1 )
     {
         gdprintk(XENLOG_WARNING, "Can't find redir item for %d EOI\n", vector);
-        return;
-    }
-
-    if ( !test_and_clear_bit(redir_num, &vioapic->isr) )
-    {
-        gdprintk(XENLOG_WARNING, "redir %d not set for %d EOI\n",
-                 redir_num, vector);
-        return;
-    }
+        goto out;
+    }
+
+    ent = &vioapic->redirtbl[gsi];
+
+    ent->fields.remote_irr = 0;
+    if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
+         !ent->fields.mask &&
+         hvm_irq->gsi_assert_count[gsi] )
+    {
+        ent->fields.remote_irr = 1;
+        vioapic_deliver(vioapic, gsi);
+    }
+
+ out:
+    spin_unlock(&hvm_irq->lock);
 }
 
 void vioapic_init(struct domain *d)
 {
     struct vioapic *vioapic = domain_vioapic(d);
-
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_init\n");
-
-    vioapic_reset(vioapic);
-
+    int i;
+
+    memset(vioapic, 0, sizeof(*vioapic));
+    for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
+        vioapic->redirtbl[i].fields.mask = 1;
     vioapic->base_address = VIOAPIC_DEFAULT_BASE_ADDRESS;
 }
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Tue Nov 21 19:22:25 2006 +0000
@@ -152,7 +152,7 @@ int vlapic_set_irq(struct vlapic *vlapic
 {
     int ret;
 
-    ret = vlapic_test_and_set_irr(vec, vlapic);
+    ret = !vlapic_test_and_set_irr(vec, vlapic);
     if ( trig )
         vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
 
@@ -371,9 +371,7 @@ struct vlapic *apic_round_robin(
     int next, old;
     struct vlapic *target = NULL;
 
-    spin_lock(&d->arch.hvm_domain.round_robin_lock);
-
-    old = next = d->arch.hvm_domain.round_info[vector];
+    old = next = d->arch.hvm_domain.irq.round_robin_prev_vcpu;
 
     do {
         if ( ++next == MAX_VIRT_CPUS ) 
@@ -386,8 +384,7 @@ struct vlapic *apic_round_robin(
         target = NULL;
     } while ( next != old );
 
-    d->arch.hvm_domain.round_info[vector] = next;
-    spin_unlock(&d->arch.hvm_domain.round_robin_lock);
+    d->arch.hvm_domain.irq.round_robin_prev_vcpu = next;
 
     return target;
 }
@@ -863,7 +860,7 @@ int cpu_has_pending_irq(struct vcpu *v)
     if ( !vlapic_accept_pic_intr(v) )
         return 0;
 
-    return plat->interrupt_request;
+    return plat->irq.vpic.irq_pending;
 }
 
 void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/io.c Tue Nov 21 19:22:25 2006 +0000
@@ -98,23 +98,17 @@ asmlinkage void vmx_intr_assist(void)
     struct vlapic *vlapic = vcpu_vlapic(v);
     struct hvm_domain *plat=&v->domain->arch.hvm_domain;
     struct periodic_time *pt = &plat->pl_time.periodic_tm;
-    struct vpic *pic= &plat->vpic;
     unsigned int idtv_info_field;
     unsigned long inst_len;
     int    has_ext_irq;
 
-    if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) {
-        pic_set_irq(pic, pt->irq, 0);
-        pic_set_irq(pic, pt->irq, 1);
+    if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
+    {
+        hvm_isa_irq_deassert(current->domain, pt->irq);
+        hvm_isa_irq_assert(current->domain, pt->irq);
     }
 
-    if (v->vcpu_id == 0) {
-        int callback_irq;
-        callback_irq =
-            v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
-        if ( callback_irq != 0 )
-            pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
-    }
+    hvm_set_callback_irq_level();
 
     if ( vlapic->flush_tpr_threshold )
         update_tpr_threshold(vlapic);
diff -r b80f00215bba -r f555a90bcc37 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/include/asm-x86/hvm/domain.h  Tue Nov 21 19:22:25 2006 +0000
@@ -16,16 +16,15 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
  */
 
 #ifndef __ASM_X86_HVM_DOMAIN_H__
 #define __ASM_X86_HVM_DOMAIN_H__
 
-#include <asm/hvm/vpic.h>
+#include <asm/hvm/irq.h>
 #include <asm/hvm/vpt.h>
 #include <asm/hvm/vlapic.h>
-#include <asm/hvm/vioapic.h>
+#include <asm/hvm/io.h>
 #include <public/hvm/params.h>
 
 struct hvm_domain {
@@ -35,13 +34,9 @@ struct hvm_domain {
     s64                    tsc_frequency;
     struct pl_time         pl_time;
 
-    struct vpic            vpic;
-    struct vioapic         vioapic;
     struct hvm_io_handler  io_handler;
 
-    unsigned char          round_info[256];
-    spinlock_t             round_robin_lock;
-    int                    interrupt_request;
+    struct hvm_irq         irq;
 
     /* hvm_print_line() logging. */
     char                   pbuf[80];
diff -r b80f00215bba -r f555a90bcc37 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h      Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/include/asm-x86/hvm/io.h      Tue Nov 21 19:22:25 2006 +0000
@@ -147,7 +147,6 @@ extern void handle_mmio(unsigned long gp
 extern void handle_mmio(unsigned long gpa);
 extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
 extern void hvm_io_assist(struct vcpu *v);
-extern void pic_irq_request(void *data, int level);
 extern int cpu_get_interrupt(struct vcpu *v, int *type);
 extern int cpu_has_pending_irq(struct vcpu *v);
 
diff -r b80f00215bba -r f555a90bcc37 xen/include/asm-x86/hvm/vioapic.h
--- a/xen/include/asm-x86/hvm/vioapic.h Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/include/asm-x86/hvm/vioapic.h Tue Nov 21 19:22:25 2006 +0000
@@ -1,5 +1,4 @@
 /*
- *
  *  Copyright (C) 2001  MandrakeSoft S.A.
  *
  *    MandrakeSoft S.A.
@@ -32,6 +31,9 @@
 
 #ifdef __ia64__
 #define VIOAPIC_IS_IOSAPIC 1
+#define VIOAPIC_NUM_PINS  24
+#else
+#define VIOAPIC_NUM_PINS  48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
 #endif
 
 #if !VIOAPIC_IS_IOSAPIC
@@ -39,8 +41,6 @@
 #else
 #define VIOAPIC_VERSION_ID 0x21 /* IOSAPIC version */
 #endif
-
-#define VIOAPIC_NUM_PINS 24
 
 #define VIOAPIC_EDGE_TRIG  0
 #define VIOAPIC_LEVEL_TRIG 1
@@ -58,9 +58,9 @@
 #define VIOAPIC_REG_VERSION 0x01
 #define VIOAPIC_REG_ARB_ID  0x02 /* x86 IOAPIC only */
 
-#define domain_vioapic(d) (&(d)->arch.hvm_domain.vioapic)
+#define domain_vioapic(d) (&(d)->arch.hvm_domain.irq.vioapic)
 #define vioapic_domain(v) (container_of((v), struct domain, \
-                                        arch.hvm_domain.vioapic))
+                                        arch.hvm_domain.irq.vioapic))
 
 union vioapic_redir_entry
 {
@@ -86,19 +86,13 @@ union vioapic_redir_entry
 };
 
 struct vioapic {
-    uint32_t irr;
-    uint32_t irr_xen; /* interrupts forced on by the hypervisor. */
-    uint32_t isr;     /* This is used for level trigger */
-    uint32_t imr;
-    uint32_t ioregsel;
-    uint32_t id;
+    uint32_t ioregsel, id;
     unsigned long base_address;
     union vioapic_redir_entry redirtbl[VIOAPIC_NUM_PINS];
 };
 
 void vioapic_init(struct domain *d);
-void vioapic_set_xen_irq(struct domain *d, int irq, int level);
-void vioapic_set_irq(struct domain *d, int irq, int level);
+void vioapic_irq_positive_edge(struct domain *d, unsigned int irq);
 void vioapic_update_EOI(struct domain *d, int vector);
 
 #endif /* __ASM_X86_HVM_VIOAPIC_H__ */
diff -r b80f00215bba -r f555a90bcc37 xen/include/asm-x86/hvm/vpic.h
--- a/xen/include/asm-x86/hvm/vpic.h    Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpic.h    Tue Nov 21 19:22:25 2006 +0000
@@ -26,14 +26,14 @@
 #ifndef __ASM_X86_HVM_VPIC_H__
 #define __ASM_X86_HVM_VPIC_H__
 
-#define domain_vpic(d) (&(d)->arch.hvm_domain.vpic)
-#define vpic_domain(v) (container_of((v), struct domain, arch.hvm_domain.vpic))
+#define domain_vpic(d) (&(d)->arch.hvm_domain.irq.vpic)
+#define vpic_domain(v) (container_of((v), struct domain, \
+                                     arch.hvm_domain.irq.vpic))
+#define vpic_lock(v)   (&container_of((v), struct hvm_irq, vpic)->lock)
 
 typedef struct PicState {
     uint8_t last_irr; /* edge detection */
     uint8_t irr; /* interrupt request register */
-    uint8_t irr_xen; /* interrupts forced on by the hypervisor e.g.
-                       the callback irq. */
     uint8_t imr; /* interrupt mask register */
     uint8_t isr; /* interrupt service register */
     uint8_t priority_add; /* highest irq priority */
@@ -54,17 +54,11 @@ struct vpic {
 struct vpic {
     /* 0 is master pic, 1 is slave pic */
     PicState pics[2];
-    void (*irq_request)(void *opaque, int level);
-    void *irq_request_opaque;
-    /* IOAPIC callback support */
-    spinlock_t lock;
+    int irq_pending;
 };
 
-void pic_set_xen_irq(void *opaque, int irq, int level);
 void pic_set_irq(struct vpic *vpic, int irq, int level);
-void pic_init(struct vpic *vpic,
-              void (*irq_request)(void *, int),
-              void *irq_request_opaque);
+void pic_init(struct vpic *vpic);
 void pic_update_irq(struct vpic *vpic); /* Caller must hold vpic->lock */
 void register_pic_io_hook(struct domain *d);
 int cpu_get_pic_interrupt(struct vcpu *v, int *type);
diff -r b80f00215bba -r f555a90bcc37 xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h   Tue Nov 21 17:34:17 2006 +0000
+++ b/xen/include/public/hvm/hvm_op.h   Tue Nov 21 19:22:25 2006 +0000
@@ -2,24 +2,52 @@
 #define __XEN_PUBLIC_HVM_HVM_OP_H__
 
 /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
-#define HVMOP_set_param     0
-#define HVMOP_get_param     1
+#define HVMOP_set_param           0
+#define HVMOP_get_param           1
 struct xen_hvm_param {
-    domid_t domid;     /* IN */
+    domid_t  domid;    /* IN */
     uint32_t index;    /* IN */
     uint64_t value;    /* IN/OUT */
 };
 typedef struct xen_hvm_param xen_hvm_param_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
 
-/* Set the logical level of one of a domain's IRQ lines. */
-#define HVMOP_set_irq_level 2
-struct xen_hvm_set_irq_level {
-    domid_t  domid;    /* Domain to be updated.          */
-    uint16_t level;    /* New level of the IRQ (0 or 1). */
-    uint32_t irq;      /* IRQ to be updated.             */
+/* Set the logical level of one of a domain's PCI INTx wires. */
+#define HVMOP_set_pci_intx_level  2
+struct xen_hvm_set_pci_intx_level {
+    /* Domain to be updated. */
+    domid_t  domid;
+    /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
+    uint8_t  domain, bus, device, intx;
+    /* Assertion level (0 = unasserted, 1 = asserted). */
+    uint8_t  level;
 };
-typedef struct xen_hvm_set_irq_level xen_hvm_set_irq_level_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_irq_level_t);
+typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t);
+
+/* Set the logical level of one of a domain's ISA IRQ wires. */
+#define HVMOP_set_isa_irq_level   3
+struct xen_hvm_set_isa_irq_level {
+    /* Domain to be updated. */
+    domid_t  domid;
+    /* ISA device identification, by ISA IRQ (0-15). */
+    uint8_t  isa_irq;
+    /* Assertion level (0 = unasserted, 1 = asserted). */
+    uint8_t  level;
+};
+typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t);
+
+#define HVMOP_set_pci_link_route  4
+struct xen_hvm_set_pci_link_route {
+    /* Domain to be updated. */
+    domid_t  domid;
+    /* PCI link identifier (0-3). */
+    uint8_t  link;
+    /* ISA IRQ (1-15), or 0 (disable link). */
+    uint8_t  isa_irq;
+};
+typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
 
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
diff -r b80f00215bba -r f555a90bcc37 tools/ioemu/target-i386-dm/piix_pci-dm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/target-i386-dm/piix_pci-dm.c  Tue Nov 21 19:22:25 2006 +0000
@@ -0,0 +1,397 @@
+/*
+ * QEMU i440FX/PIIX3 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+typedef uint32_t pci_addr_t;
+#include "hw/pci_host.h"
+
+typedef PCIHostState I440FXState;
+
+static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
+{
+    I440FXState *s = opaque;
+    s->config_reg = val;
+}
+
+static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
+{
+    I440FXState *s = opaque;
+    return s->config_reg;
+}
+
+static void i440fx_set_irq(PCIDevice *pci_dev, void *pic, int intx, int level)
+{
+    xc_hvm_set_pci_intx_level(xc_handle, domid, 0, 0, pci_dev->devfn >> 3,
+                              intx, level);
+}
+
+PCIBus *i440fx_init(void)
+{
+    PCIBus *b;
+    PCIDevice *d;
+    I440FXState *s;
+
+    s = qemu_mallocz(sizeof(I440FXState));
+    b = pci_register_bus(i440fx_set_irq, NULL, 0);
+    s->bus = b;
+
+    register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
+    register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
+
+    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
+    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
+    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
+    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
+    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
+    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+
+    d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0, 
+                            NULL, NULL);
+
+    d->config[0x00] = 0x86; // vendor_id
+    d->config[0x01] = 0x80;
+    d->config[0x02] = 0x37; // device_id
+    d->config[0x03] = 0x12;
+    d->config[0x08] = 0x02; // revision
+    d->config[0x0a] = 0x00; // class_sub = host2pci
+    d->config[0x0b] = 0x06; // class_base = PCI_bridge
+    d->config[0x0e] = 0x00; // header_type
+    return b;
+}
+
+/* PIIX3 PCI to ISA bridge */
+
+static PCIDevice *piix3_dev;
+
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    /* This is the barber's pole mapping used by Xen. */
+    return (irq_num + (pci_dev->devfn >> 3)) & 3;
+}
+
+static void piix3_write_config(PCIDevice *d, 
+                               uint32_t address, uint32_t val, int len)
+{
+    int i;
+
+    /* Scan for updates to PCI link routes (0x60-0x63). */
+    for (i = 0; i < len; i++) {
+        uint8_t v = (val >> (8*i)) & 0xff;
+        if (v & 0x80)
+            v = 0;
+        v &= 0xf;
+        if (((address+i) >= 0x60) && ((address+i) <= 0x63))
+            xc_hvm_set_pci_link_route(xc_handle, domid, address + i - 0x60, v);
+    }
+
+    /* Hand off to default logic. */
+    pci_default_write_config(d, address, val, len);
+}
+
+static void piix3_reset(PCIDevice *d)
+{
+    uint8_t *pci_conf = d->config;
+
+    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 0x80;
+    pci_conf[0x61] = 0x80;
+    pci_conf[0x62] = 0x80;
+    pci_conf[0x63] = 0x80;
+    pci_conf[0x69] = 0x02;
+    pci_conf[0x70] = 0x80;
+    pci_conf[0x76] = 0x0c;
+    pci_conf[0x77] = 0x0c;
+    pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
+    pci_conf[0xa0] = 0x08;
+    pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
+    pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+}
+
+int piix3_init(PCIBus *bus)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
+    d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
+                                    -1, NULL, piix3_write_config);
+    register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
+
+    piix3_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    pci_conf[0x03] = 0x70;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix3_reset(d);
+    return d->devfn;
+}
+
+/***********************************************************/
+/* XXX: the following should be moved to the PC BIOS */
+
+static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
+{
+    return cpu_inb(NULL, addr);
+}
+
+static void isa_outb(uint32_t val, uint32_t addr)
+{
+    cpu_outb(NULL, addr, val);
+}
+
+static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
+{
+    return cpu_inw(NULL, addr);
+}
+
+static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
+{
+    cpu_outw(NULL, addr, val);
+}
+
+static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
+{
+    return cpu_inl(NULL, addr);
+}
+
+static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
+{
+    cpu_outl(NULL, addr, val);
+}
+
+static uint32_t pci_bios_io_addr;
+static uint32_t pci_bios_mem_addr;
+/* host irqs corresponding to PCI irqs A-D */
+static uint8_t pci_irqs[4] = { 10, 11, 10, 11 };
+
+static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+    PCIBus *s = d->bus;
+    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
+    pci_data_write(s, addr, val, 4);
+}
+
+static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+    PCIBus *s = d->bus;
+    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
+    pci_data_write(s, addr, val, 2);
+}
+
+static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+    PCIBus *s = d->bus;
+    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
+    pci_data_write(s, addr, val, 1);
+}
+
+static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, 
uint32_t addr)
+{
+    PCIBus *s = d->bus;
+    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
+    return pci_data_read(s, addr, 4);
+}
+
+static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
+{
+    PCIBus *s = d->bus;
+    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
+    return pci_data_read(s, addr, 2);
+}
+
+static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
+{
+    PCIBus *s = d->bus;
+    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
+    return pci_data_read(s, addr, 1);
+}
+
+static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
+{
+    PCIIORegion *r;
+    uint16_t cmd;
+    uint32_t ofs;
+
+    if ( region_num == PCI_ROM_SLOT ) {
+        ofs = 0x30;
+    }else{
+        ofs = 0x10 + region_num * 4;
+    }
+
+    pci_config_writel(d, ofs, addr);
+    r = &d->io_regions[region_num];
+
+    /* enable memory mappings */
+    cmd = pci_config_readw(d, PCI_COMMAND);
+    if ( region_num == PCI_ROM_SLOT )
+        cmd |= 2;
+    else if (r->type & PCI_ADDRESS_SPACE_IO)
+        cmd |= 1;
+    else
+        cmd |= 2;
+    pci_config_writew(d, PCI_COMMAND, cmd);
+}
+
+static void pci_bios_init_device(PCIDevice *d)
+{
+    int class;
+    PCIIORegion *r;
+    uint32_t *paddr;
+    int i, pin, pic_irq, vendor_id, device_id;
+
+    class = pci_config_readw(d, PCI_CLASS_DEVICE);
+    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
+    device_id = pci_config_readw(d, PCI_DEVICE_ID);
+    switch(class) {
+    case 0x0101:
+        if (vendor_id == 0x8086 && device_id == 0x7010) {
+            /* PIIX3 IDE */
+            pci_config_writew(d, 0x40, 0x8000); // enable IDE0
+            pci_config_writew(d, 0x42, 0x8000); // enable IDE1
+            goto default_map;
+        } else {
+            /* IDE: we map it as in ISA mode */
+            pci_set_io_region_addr(d, 0, 0x1f0);
+            pci_set_io_region_addr(d, 1, 0x3f4);
+            pci_set_io_region_addr(d, 2, 0x170);
+            pci_set_io_region_addr(d, 3, 0x374);
+        }
+        break;
+    case 0x0680:
+        if (vendor_id == 0x8086 && device_id == 0x7113) {
+            /*
+             * PIIX4 ACPI PM.
+             * Special device with special PCI config space. No ordinary BARs.
+             */
+            pci_config_writew(d, 0x20, 0x0000); // No smb bus IO enable
+            pci_config_writew(d, 0x22, 0x0000);
+            pci_config_writew(d, 0x3c, 0x0009); // Hardcoded IRQ9
+            pci_config_writew(d, 0x3d, 0x0001);
+        }
+        break;
+    case 0x0300:
+        if (vendor_id != 0x1234)
+            goto default_map;
+        /* VGA: map frame buffer to default Bochs VBE address */
+        pci_set_io_region_addr(d, 0, 0xE0000000);
+        break;
+    case 0x0800:
+        /* PIC */
+        vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
+        device_id = pci_config_readw(d, PCI_DEVICE_ID);
+        if (vendor_id == 0x1014) {
+            /* IBM */
+            if (device_id == 0x0046 || device_id == 0xFFFF) {
+                /* MPIC & MPIC2 */
+                pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
+            }
+        }
+        break;
+    case 0xff00:
+        if (vendor_id == 0x0106b &&
+            (device_id == 0x0017 || device_id == 0x0022)) {
+            /* macio bridge */
+            pci_set_io_region_addr(d, 0, 0x80800000);
+        }
+        break;
+    default:
+    default_map:
+        /* default memory mappings */
+        for(i = 0; i < PCI_NUM_REGIONS; i++) {
+            r = &d->io_regions[i];
+            if (r->size) {
+                if (r->type & PCI_ADDRESS_SPACE_IO)
+                    paddr = &pci_bios_io_addr;
+                else
+                    paddr = &pci_bios_mem_addr;
+                *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
+                pci_set_io_region_addr(d, i, *paddr);
+                *paddr += r->size;
+            }
+        }
+        break;
+    }
+
+    /* map the interrupt */
+    pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
+    if (pin != 0) {
+        pin = pci_slot_get_pirq(d, pin - 1);
+        pic_irq = pci_irqs[pin];
+        pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
+    }
+}
+
+/*
+ * This function initializes the PCI devices as a normal PCI BIOS
+ * would do. It is provided just in case the BIOS has no support for
+ * PCI.
+ */
+void pci_bios_init(void)
+{
+    int i, irq;
+    uint8_t elcr[2];
+
+    pci_bios_io_addr = 0xc000;
+    pci_bios_mem_addr = HVM_BELOW_4G_MMIO_START;
+
+    /* activate IRQ mappings */
+    elcr[0] = 0x00;
+    elcr[1] = 0x00;
+    for(i = 0; i < 4; i++) {
+        irq = pci_irqs[i];
+        /* set to trigger level */
+        elcr[irq >> 3] |= (1 << (irq & 7));
+        /* activate irq remapping in PIIX */
+        pci_config_writeb(piix3_dev, 0x60 + i, irq);
+    }
+    isa_outb(elcr[0], 0x4d0);
+    isa_outb(elcr[1], 0x4d1);
+
+    pci_for_each_device(pci_bios_init_device);
+}
+
diff -r b80f00215bba -r f555a90bcc37 xen/arch/x86/hvm/irq.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/irq.c    Tue Nov 21 19:22:25 2006 +0000
@@ -0,0 +1,227 @@
+/******************************************************************************
+ * irq.c
+ * 
+ * Interrupt distribution and delivery logic.
+ * 
+ * Copyright (c) 2006, K A Fraser, XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/event.h>
+#include <xen/sched.h>
+#include <asm/hvm/domain.h>
+
+void hvm_pci_intx_assert(
+    struct domain *d, unsigned int device, unsigned int intx)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    unsigned int gsi, link, isa_irq;
+
+    ASSERT((device <= 31) && (intx <= 3));
+
+    spin_lock(&hvm_irq->lock);
+
+    if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx) )
+        goto out;
+
+    gsi = hvm_pci_intx_gsi(device, intx);
+    if ( hvm_irq->gsi_assert_count[gsi]++ == 0 )
+        vioapic_irq_positive_edge(d, gsi);
+
+    link    = hvm_pci_intx_link(device, intx);
+    isa_irq = hvm_irq->pci_link_route[link];
+    if ( (hvm_irq->pci_link_assert_count[link]++ == 0) && isa_irq &&
+         (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
+    {
+        vioapic_irq_positive_edge(d, isa_irq);
+        pic_set_irq(&hvm_irq->vpic, isa_irq, 1);
+    }
+
+ out:
+    spin_unlock(&hvm_irq->lock);
+}
+
+void hvm_pci_intx_deassert(
+    struct domain *d, unsigned int device, unsigned int intx)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    unsigned int gsi, link, isa_irq;
+
+    ASSERT((device <= 31) && (intx <= 3));
+
+    spin_lock(&hvm_irq->lock);
+
+    if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx) )
+        goto out;
+
+    gsi = hvm_pci_intx_gsi(device, intx);
+    --hvm_irq->gsi_assert_count[gsi];
+
+    link    = hvm_pci_intx_link(device, intx);
+    isa_irq = hvm_irq->pci_link_route[link];
+    if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq &&
+         (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
+        pic_set_irq(&hvm_irq->vpic, isa_irq, 0);
+
+ out:
+    spin_unlock(&hvm_irq->lock);
+}
+
+void hvm_isa_irq_assert(
+    struct domain *d, unsigned int isa_irq)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    ASSERT(isa_irq <= 15);
+
+    spin_lock(&hvm_irq->lock);
+
+    if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq) &&
+         (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
+    {
+        vioapic_irq_positive_edge(d, isa_irq);
+        pic_set_irq(&hvm_irq->vpic, isa_irq, 1);
+    }
+
+    spin_unlock(&hvm_irq->lock);
+}
+
+void hvm_isa_irq_deassert(
+    struct domain *d, unsigned int isa_irq)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    ASSERT(isa_irq <= 15);
+
+    spin_lock(&hvm_irq->lock);
+
+    if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq) &&
+         (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
+        pic_set_irq(&hvm_irq->vpic, isa_irq, 0);
+
+    spin_unlock(&hvm_irq->lock);
+}
+
+void hvm_set_callback_irq_level(void)
+{
+    struct vcpu *v = current;
+    struct domain *d = v->domain;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    unsigned int gsi = hvm_irq->callback_gsi;
+
+    /* Fast lock-free tests. */
+    if ( (v->vcpu_id != 0) || (gsi == 0) )
+        return;
+
+    spin_lock(&hvm_irq->lock);
+
+    gsi = hvm_irq->callback_gsi;
+    if ( gsi == 0 )
+        goto out;
+
+    if ( local_events_need_delivery() )
+    {
+        if ( !__test_and_set_bit(0, &hvm_irq->callback_irq_wire) &&
+             (hvm_irq->gsi_assert_count[gsi]++ == 0) )
+        {
+            vioapic_irq_positive_edge(d, gsi);
+            if ( gsi <= 15 )
+                pic_set_irq(&hvm_irq->vpic, gsi, 1);
+        }
+    }
+    else
+    {
+        if ( __test_and_clear_bit(0, &hvm_irq->callback_irq_wire) &&
+             (--hvm_irq->gsi_assert_count[gsi] == 0) )
+        {
+            if ( gsi <= 15 )
+                pic_set_irq(&hvm_irq->vpic, gsi, 0);
+        }
+    }
+
+ out:
+    spin_unlock(&hvm_irq->lock);
+}
+
+void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    u8 old_isa_irq;
+
+    ASSERT((link <= 3) && (isa_irq <= 15));
+
+    spin_lock(&hvm_irq->lock);
+
+    old_isa_irq = hvm_irq->pci_link_route[link];
+    if ( old_isa_irq == isa_irq )
+        goto out;
+    hvm_irq->pci_link_route[link] = isa_irq;
+
+    if ( hvm_irq->pci_link_assert_count[link] == 0 )
+        goto out;
+
+    if ( old_isa_irq && (--hvm_irq->gsi_assert_count[old_isa_irq] == 0) )
+        pic_set_irq(&hvm_irq->vpic, isa_irq, 0);
+
+    if ( isa_irq && (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
+    {
+        vioapic_irq_positive_edge(d, isa_irq);
+        pic_set_irq(&hvm_irq->vpic, isa_irq, 1);
+    }
+
+ out:
+    spin_unlock(&hvm_irq->lock);
+
+    dprintk(XENLOG_G_INFO, "Dom%u PCI link %u changed %u -> %u\n",
+            d->domain_id, link, old_isa_irq, isa_irq);
+}
+
+void hvm_set_callback_gsi(struct domain *d, unsigned int gsi)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    unsigned int old_gsi;
+
+    if ( gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count) )
+        gsi = 0;
+
+    spin_lock(&hvm_irq->lock);
+
+    old_gsi = hvm_irq->callback_gsi;
+    if ( old_gsi == gsi )
+        goto out;
+    hvm_irq->callback_gsi = gsi;
+
+    if ( !test_bit(0, &hvm_irq->callback_irq_wire) )
+        goto out;
+
+    if ( old_gsi && (--hvm_irq->gsi_assert_count[old_gsi] == 0) )
+        if ( old_gsi <= 15 )
+            pic_set_irq(&hvm_irq->vpic, old_gsi, 0);
+
+    if ( gsi && (hvm_irq->gsi_assert_count[gsi]++ == 0) )
+    {
+        vioapic_irq_positive_edge(d, gsi);
+        if ( gsi <= 15 )
+            pic_set_irq(&hvm_irq->vpic, gsi, 1);
+    }
+
+ out:
+    spin_unlock(&hvm_irq->lock);
+
+    dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n",
+            d->domain_id, old_gsi, gsi);
+}
diff -r b80f00215bba -r f555a90bcc37 xen/include/asm-x86/hvm/irq.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hvm/irq.h     Tue Nov 21 19:22:25 2006 +0000
@@ -0,0 +1,107 @@
+/******************************************************************************
+ * irq.h
+ * 
+ * Interrupt distribution and delivery logic.
+ * 
+ * Copyright (c) 2006, K A Fraser, XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __ASM_X86_HVM_IRQ_H__
+#define __ASM_X86_HVM_IRQ_H__
+
+#include <xen/types.h>
+#include <xen/spinlock.h>
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/vioapic.h>
+
+struct hvm_irq {
+    /* Lock protects access to all other fields. */
+    spinlock_t lock;
+
+    /*
+     * Virtual interrupt wires for a single PCI bus.
+     * Indexed by: device*4 + INTx#.
+     */
+    DECLARE_BITMAP(pci_intx, 32*4);
+
+    /*
+     * Virtual interrupt wires for ISA devices.
+     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
+     */
+    DECLARE_BITMAP(isa_irq, 16);
+
+    /* Virtual interrupt wire and GSI link for paravirtual platform driver. */
+    DECLARE_BITMAP(callback_irq_wire, 1);
+    unsigned int callback_gsi;
+
+    /*
+     * PCI-ISA interrupt router.
+     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
+     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
+     * The router provides a programmable mapping from each link to a GSI.
+     */
+    u8 pci_link_route[4];
+
+    /* Number of INTx wires asserting each PCI-ISA link. */
+    u8 pci_link_assert_count[4];
+
+    /*
+     * Number of wires asserting each GSI.
+     * 
+     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space.
+     * PCI links map into this space via the PCI-ISA bridge.
+     * 
+     * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
+     * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
+     */
+    u8 gsi_assert_count[VIOAPIC_NUM_PINS];
+
+    /*
+     * GSIs map onto PIC/IO-APIC in the usual way:
+     *  0-7:  Master 8259 PIC, IO-APIC pins 0-7
+     *  8-15: Slave  8259 PIC, IO-APIC pins 8-15
+     *  16+ : IO-APIC pins 16+
+     */
+    struct vpic    vpic;
+    struct vioapic vioapic;
+
+    /* Last VCPU that was delivered a LowestPrio interrupt. */
+    u8 round_robin_prev_vcpu;
+};
+
+#define hvm_pci_intx_gsi(dev, intx)  \
+    (((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16)
+#define hvm_pci_intx_link(dev, intx) \
+    (((dev) + (intx)) & 3)
+
+/* Modify state of a PCI INTx wire. */
+void hvm_pci_intx_assert(
+    struct domain *d, unsigned int device, unsigned int intx);
+void hvm_pci_intx_deassert(
+    struct domain *d, unsigned int device, unsigned int intx);
+
+/* Modify state of an ISA device's IRQ wire. */
+void hvm_isa_irq_assert(
+    struct domain *d, unsigned int isa_irq);
+void hvm_isa_irq_deassert(
+    struct domain *d, unsigned int isa_irq);
+
+void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
+
+void hvm_set_callback_irq_level(void);
+void hvm_set_callback_gsi(struct domain *d, unsigned int gsi);
+
+#endif /* __ASM_X86_HVM_IRQ_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [HVM] Reworked interrupt distribution logic., Xen patchbot-unstable <=