[SeaBIOS] [PATCH 2/2] q35: Add new PCI slot to irq routing function

2013-01-22 Thread Alex Williamson
q35/ich9 doesn't use the same interrupt mapping function as
i440fx/piix.  PIRQA:D and PIRQE:H are programmed identically, but we
start at index 0, not index -1.  Slots 25 through 31 are also
programmed independently.

When running qemu w/o this patch, a device at address 0:6.0 will have
its PCI interrupt line register programmed with irq 10 (as seen by
info pci), but it actually uses irq 11 (as reported the guest).  Half
of the interrupt lines are misprogrammedi like this.  Functionally, a
fully emulated qemu guest doesn't care much, but when we try to use
device assignment, we really need to know the correct irqs.

Signed-off-by: Alex Williamson alex.william...@redhat.com
---
 src/pciinit.c |   35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/pciinit.c b/src/pciinit.c
index 857e8af..ddac7e7 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -91,8 +91,10 @@ const u8 pci_irqs[4] = {
 10, 10, 11, 11
 };
 
+static int (*pci_slot_get_irq)(struct pci_device *pci, int pin);
+
 // Return the global irq number corresponding to a host bus device irq pin.
-static int pci_slot_get_irq(struct pci_device *pci, int pin)
+static int piix_pci_slot_get_irq(struct pci_device *pci, int pin)
 {
 int slot_addend = 0;
 
@@ -104,6 +106,33 @@ static int pci_slot_get_irq(struct pci_device *pci, int 
pin)
 return pci_irqs[(pin - 1 + slot_addend)  3];
 }
 
+static int mch_pci_slot_get_irq(struct pci_device *pci, int pin)
+{
+int irq, slot_addend = 0;
+
+while (pci-parent != NULL) {
+slot_addend += pci_bdf_to_dev(pci-bdf);
+pci = pci-parent;
+}
+slot_addend += pci_bdf_to_dev(pci-bdf);
+
+switch (slot_addend) {
+/* Slots 0-24 rotate slot:pin mapping similar to piix above, but
+   with a different starting index - see q35-acpi-dsdt.dsl */ 
+case 0 ... 24:
+irq = pci_irqs[(pin - 1 + slot_addend)  3];
+break;
+/* Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H) */
+case 25 ... 31:
+irq = pci_irqs[pin - 1];
+break;
+default:
+irq = 0;
+}
+
+return irq;
+}
+
 /* PIIX3/PIIX4 PCI to ISA bridge */
 static void piix_isa_bridge_init(struct pci_device *pci, void *arg)
 {
@@ -292,6 +321,8 @@ void i440fx_mem_addr_init(struct pci_device *dev, void *arg)
 pcimem_start = 0x8000;
 else if (RamSize = 0xc000)
 pcimem_start = 0xc000;
+
+pci_slot_get_irq = piix_pci_slot_get_irq;
 }
 
 void mch_mem_addr_init(struct pci_device *dev, void *arg)
@@ -310,6 +341,8 @@ void mch_mem_addr_init(struct pci_device *dev, void *arg)
 
 /* setup pci i/o window (above mmconfig) */
 pcimem_start = addr + size;
+
+pci_slot_get_irq = mch_pci_slot_get_irq;
 }
 
 static const struct pci_device_id pci_platform_tbl[] = {


___
SeaBIOS mailing list
SeaBIOS@seabios.org
http://www.seabios.org/mailman/listinfo/seabios


Re: [SeaBIOS] [PATCH 2/2] q35: Add new PCI slot to irq routing function

2013-01-22 Thread Alex Williamson
On Tue, 2013-01-22 at 15:12 -0700, Alex Williamson wrote:
 q35/ich9 doesn't use the same interrupt mapping function as
 i440fx/piix.  PIRQA:D and PIRQE:H are programmed identically, but we
 start at index 0, not index -1.  Slots 25 through 31 are also
 programmed independently.
 
 When running qemu w/o this patch, a device at address 0:6.0 will have
 its PCI interrupt line register programmed with irq 10 (as seen by
 info pci), but it actually uses irq 11 (as reported the guest).  Half
 of the interrupt lines are misprogrammedi like this.  Functionally, a
 fully emulated qemu guest doesn't care much, but when we try to use
 device assignment, we really need to know the correct irqs.
 
 Signed-off-by: Alex Williamson alex.william...@redhat.com
 ---
  src/pciinit.c |   35 ++-
  1 file changed, 34 insertions(+), 1 deletion(-)
 
 diff --git a/src/pciinit.c b/src/pciinit.c
 index 857e8af..ddac7e7 100644
 --- a/src/pciinit.c
 +++ b/src/pciinit.c
 @@ -91,8 +91,10 @@ const u8 pci_irqs[4] = {
  10, 10, 11, 11
  };
  
 +static int (*pci_slot_get_irq)(struct pci_device *pci, int pin);
 +
  // Return the global irq number corresponding to a host bus device irq pin.
 -static int pci_slot_get_irq(struct pci_device *pci, int pin)
 +static int piix_pci_slot_get_irq(struct pci_device *pci, int pin)
  {
  int slot_addend = 0;
  
 @@ -104,6 +106,33 @@ static int pci_slot_get_irq(struct pci_device *pci, int 
 pin)
  return pci_irqs[(pin - 1 + slot_addend)  3];
  }
  
 +static int mch_pci_slot_get_irq(struct pci_device *pci, int pin)
 +{
 +int irq, slot_addend = 0;
 +
 +while (pci-parent != NULL) {
 +slot_addend += pci_bdf_to_dev(pci-bdf);
 +pci = pci-parent;
 +}
 +slot_addend += pci_bdf_to_dev(pci-bdf);
 +
 +switch (slot_addend) {

Nak, I'm not accounting for the bridges properly here.

 +/* Slots 0-24 rotate slot:pin mapping similar to piix above, but
 +   with a different starting index - see q35-acpi-dsdt.dsl */ 
 +case 0 ... 24:
 +irq = pci_irqs[(pin - 1 + slot_addend)  3];
 +break;
 +/* Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H) */
 +case 25 ... 31:
 +irq = pci_irqs[pin - 1];
 +break;
 +default:
 +irq = 0;
 +}
 +
 +return irq;
 +}
 +
  /* PIIX3/PIIX4 PCI to ISA bridge */
  static void piix_isa_bridge_init(struct pci_device *pci, void *arg)
  {
 @@ -292,6 +321,8 @@ void i440fx_mem_addr_init(struct pci_device *dev, void 
 *arg)
  pcimem_start = 0x8000;
  else if (RamSize = 0xc000)
  pcimem_start = 0xc000;
 +
 +pci_slot_get_irq = piix_pci_slot_get_irq;
  }
  
  void mch_mem_addr_init(struct pci_device *dev, void *arg)
 @@ -310,6 +341,8 @@ void mch_mem_addr_init(struct pci_device *dev, void *arg)
  
  /* setup pci i/o window (above mmconfig) */
  pcimem_start = addr + size;
 +
 +pci_slot_get_irq = mch_pci_slot_get_irq;
  }
  
  static const struct pci_device_id pci_platform_tbl[] = {
 




___
SeaBIOS mailing list
SeaBIOS@seabios.org
http://www.seabios.org/mailman/listinfo/seabios