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 = 0x80000000;
>      else if (RamSize <= 0xc0000000)
>          pcimem_start = 0xc0000000;
> +
> +    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

Reply via email to