<div dir="ltr">hw/isa/lpc_ich9.c<div><br></div><div>this patch adds:</div><div>* debug output, if enabled</div><div>* enforces correct intel config, if enabled. (unsure if this is needed)</div><div>* redirects some PCI Config to host</div><div>* uses hosts LPC device id<br><div><br></div><div>patch</div><div>---------------------</div><div><br></div><div><div>diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c</div><div>index b846d81..e6a7fbd 100644</div><div>--- a/hw/isa/lpc_ich9.c</div><div>+++ b/hw/isa/lpc_ich9.c</div><div>@@ -6,6 +6,7 @@</div><div>  *               Isaku Yamahata <yamahata at valinux co jp></div><div>  *               VA Linux Systems Japan K.K.</div><div>  * Copyright (C) 2012 Jason Baron <<a href="mailto:jbaron@redhat.com">jbaron@redhat.com</a>></div><div>+ * Copyright (C) 2014 Andrew Barnes <<a href="mailto:andy@outsideglobe.com">andy@outsideglobe.com</a>> IGD Support</div><div>  *</div><div>  * This is based on piix_pci.c, but heavily modified.</div><div>  *</div><div>@@ -46,6 +47,16 @@</div><div> #include "exec/address-spaces.h"</div><div> #include "sysemu/sysemu.h"</div><div> </div><div>+/* #define DEBUG_LPC */</div><div>+#ifdef DEBUG_LPC</div><div>+#  define LPC_DPRINTF(format, ...) print("LPC: " format, ## __VA_ARGS__)</div><div>+#else</div><div>+#  define LPC_DPRINTF(format, ...) do {} while (0)</div><div>+#endif</div><div>+</div><div>+/* For intel-spec conforming config */</div><div>+#define CORRECT_CONFIG</div><div>+</div><div> static int ich9_lpc_sci_irq(ICH9LPCState *lpc);</div><div> </div><div> /*****************************************************************************/</div><div>@@ -53,6 +64,10 @@ static int ich9_lpc_sci_irq(ICH9LPCState *lpc);</div><div> </div><div> static void ich9_lpc_reset(DeviceState *qdev);</div><div> </div><div>+/* BEWARE: only set this if you are passing IGD through to guest */</div><div>+/* TODO: detect IGD automatically */</div><div>+static bool IGD_PASSTHROUGH = true;</div><div>+</div><div> /* chipset configuration register</div><div>  * to access chipset configuration registers, pci_[sg]et_{byte, word, long}</div><div>  * are used.</div><div>@@ -425,6 +440,9 @@ static void ich9_lpc_config_write(PCIDevice *d,</div><div>     ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);</div><div>     uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA);</div><div> </div><div>+    LPC_DPRINTF("%s(%04x:%02x:%02x.%x, @0x%x, 0x%x, len=0x%x)\n", __func__,</div><div>+                0000, 00, PCI_SLOT(d->devfn),PCI_FUNC(d->devfn), addr, val, len);</div><div>+</div><div>     pci_default_write_config(d, addr, val, len);</div><div>     if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4)) {</div><div>         ich9_lpc_pmbase_update(lpc);</div><div>@@ -440,6 +458,34 @@ static void ich9_lpc_config_write(PCIDevice *d,</div><div>     }</div><div> }</div><div> </div><div>+static uint32_t ich9_lpc_config_read(PCIDevice *d,</div><div>+                                     uint32_t addr, int len)</div><div>+{</div><div>+    uint32_t val;</div><div>+    if (IGD_PASSTHROUGH)</div><div>+    {</div><div>+<span class="" style="white-space:pre">  </span>if (ranges_overlap(addr, len, 0x2c, 2) || /* SVID - Subsystem Vendor Identification */</div><div>+<span class="" style="white-space:pre">    </span>    ranges_overlap(addr, len, 0x2e, 2))   /* SID - Subsystem Identificaion */</div><div>+<span class="" style="white-space:pre">  </span>{</div><div>+<span class="" style="white-space:pre">         </span>val = host_pci_read_config(0,PCI_SLOT(d->devfn),PCI_FUNC(d->devfn),addr,len);</div><div>+<span class="" style="white-space:pre">       </span>}</div><div>+<span class="" style="white-space:pre"> </span>else</div><div>+<span class="" style="white-space:pre">      </span>{</div><div>+<span class="" style="white-space:pre">         </span>goto defaultread;</div><div>+<span class="" style="white-space:pre"> </span>}</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+defaultread:</div><div>+<span class="" style="white-space:pre">     </span>val = pci_default_read_config(d,addr,len);</div><div>+    }</div><div>+</div><div>+    LPC_DPRINTF("%s(%04x:%02x:%02x.%x, @0x%x, len=0x%x) %x\n", __func__,</div><div>+                0000, 00, PCI_SLOT(d->devfn),PCI_FUNC(d->devfn), addr, len, val);</div><div>+</div><div>+    return val;</div><div>+}</div><div>+</div><div> static void ich9_lpc_reset(DeviceState *qdev)</div><div> {</div><div>     PCIDevice *d = PCI_DEVICE(qdev);</div><div>@@ -577,6 +623,13 @@ static int ich9_lpc_init(PCIDevice *d)</div><div> </div><div>     isa_bus = isa_bus_new(&d->qdev, get_system_io());</div><div> </div><div>+    #ifdef CORRECT_CONFIG</div><div>+        pci_set_word(d->wmask + PCI_COMMAND,</div><div>+                    (PCI_COMMAND_SERR | PCI_COMMAND_PARITY));</div><div>+        pci_set_word(d->config + PCI_COMMAND,</div><div>+                    (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER));</div><div>+    #endif</div><div>+</div><div>     pci_set_long(d->wmask + ICH9_LPC_PMBASE,</div><div>                  ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);</div><div> </div><div>@@ -665,11 +718,20 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)</div><div>     k->init = ich9_lpc_init;</div><div>     dc->vmsd = &vmstate_ich9_lpc;</div><div>     k->config_write = ich9_lpc_config_write;</div><div>+    k->config_read = ich9_lpc_config_read;</div><div>     dc->desc = "ICH9 LPC bridge";</div><div>     k->vendor_id = PCI_VENDOR_ID_INTEL;</div><div>     k->device_id = PCI_DEVICE_ID_INTEL_ICH9_8;</div><div>     k->revision = ICH9_A2_LPC_REVISION;</div><div>     k->class_id = PCI_CLASS_BRIDGE_ISA;</div><div>+</div><div>+    /* For a UN-MODIFIED guest, the following 3 registers need to be read from the host.</div><div>+     * alternatively, modify i915_drv.c, intel_detect_pch, add a check for</div><div>+     * PCI_DEVICE_ID_INTEL_ICH9_8 and copy the settings from the PCH you desire */</div><div>+    k->vendor_id = host_pci_read_config(0,0x1f,0,0x00,2);</div><div>+    k->device_id = host_pci_read_config(0,0x1f,0,0x02,2);</div><div>+//    k->revision = host_pci_read_config(0,0x1f,0,0x08,1);</div><div>+</div><div>     /*</div><div>      * Reason: part of ICH9 southbridge, needs to be wired up by</div><div>      * pc_q35_init()</div></div></div></div>