From: Jean Guyader Date: Thu, 9 Oct 2008 16:45:11 +0000 (+0100) Subject: - Add some pci function to read pci register value on the host's pci X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=87277df51b66ef2547c25273d099a64e44a51166;p=xenclient%2Fioemu.git - Add some pci function to read pci register value on the host's pci bus. - Map and unmap the legacy ioport/iomem when we attach/detach the device. --- diff --git a/hw/pass-through.c b/hw/pass-through.c index 77ab759a..9bb13fe2 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -28,6 +28,8 @@ #include "pt-msi.h" #include "qemu-xen.h" +extern int vga_passthrough; + struct php_dev { struct pt_dev *pt_dev; uint8_t valid; @@ -2876,6 +2878,7 @@ struct pt_dev * register_real_device(PCIBus *e_bus, uint8_t e_device, e_intx; struct pci_config_cf8 machine_bdf; int free_pci_slot = -1; + uint16_t class, vendor_id; PT_LOG("Assigning real physical device %02x:%02x.%x ...\n", r_bus, r_dev, r_func); @@ -2983,6 +2986,29 @@ struct pt_dev * register_real_device(PCIBus *e_bus, *(uint16_t *)(&assigned_device->dev.config[0x04])); } + /* Map legacy ioport and iomem, for specific devices */ + vendor_id = pci_read_word(pci_dev, 0x00); + class = pci_read_word(pci_dev, 0x0a); + + PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); + if ( vga_passthrough && class == 0x0300 ) + { + PT_LOG("add an intel graphic card\n"); + + rc = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, + DPCI_ADD_MAPPING); + rc |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, + DPCI_ADD_MAPPING); + if ( vendor_id == 0x8086 ) + rc |= xc_domain_memory_mapping(xc_handle, domid, 0x7d5ae, 0x7d5ae, 2, + DPCI_ADD_MAPPING); + if ( rc != 0 ) + { + PT_LOG("legacy mapping failed !\n"); + return NULL; + } + } + out: PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n", r_bus, r_dev, r_func); @@ -2999,6 +3025,7 @@ int unregister_real_device(int php_slot) uint32_t machine_irq; uint32_t bdf = 0; int rc = -1; + uint16_t class, vendor_id; if ( php_slot < 0 || php_slot >= PHP_SLOT_LEN ) return -1; @@ -3035,6 +3062,30 @@ int unregister_real_device(int php_slot) /* unregister real device's MMIO/PIO BARs */ pt_unregister_regions(assigned_device); + + /* unmap legacy ioport and iomem, for specific devices */ + vendor_id = pci_read_word(pci_dev, 0x00); + class = pci_read_word(pci_dev, 0x0a); + + PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); + if ( vga_passthrough && class == 0x0300 ) + { + PT_LOG("remove an intel graphic card\n"); + + rc = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, + DPCI_REMOVE_MAPPING); + rc |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, + DPCI_REMOVE_MAPPING); + if ( vendor_id == 0x8086 ) + rc |= xc_domain_memory_mapping(xc_handle, domid, 0x7d5ae, 0x7d5ae, 2, + DPCI_REMOVE_MAPPING); + if ( rc != 0 ) + { + PT_LOG("legacy unmapping failed !\n"); + return NULL; + } + } + /* deassign the dev to dom0 */ bdf |= (pci_dev->bus & 0xff) << 16; @@ -3149,3 +3200,42 @@ int pt_init(PCIBus *e_bus, const char *direct_pci) return 0; } + +u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr) +{ + struct pci_dev* pci_dev; + u8 val; + + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); + if (!pci_dev) + return 0; + val = pci_read_byte(pci_dev, addr); + pci_free_dev(pci_dev); + return val; +} + +u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr) +{ + struct pci_dev* pci_dev; + u16 val; + + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); + if (!pci_dev) + return 0; + val = pci_read_word(pci_dev, addr); + pci_free_dev(pci_dev); + return val; +} + +u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr) +{ + struct pci_dev* pci_dev; + u32 val; + + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); + if (!pci_dev) + return 0; + val = pci_read_long(pci_dev, addr); + pci_free_dev(pci_dev); + return val; +} diff --git a/hw/pass-through.h b/hw/pass-through.h index bc3ef8cb..b08af8cb 100644 --- a/hw/pass-through.h +++ b/hw/pass-through.h @@ -292,5 +292,9 @@ struct pt_reg_info_tbl { } u; }; +u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr); +u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr); +u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr); + #endif /* __PASSTHROUGH_H__ */