1*f7d6f3faSMarcel Apfelbaum /* 2*f7d6f3faSMarcel Apfelbaum * Generic PCI Express Root Port emulation 3*f7d6f3faSMarcel Apfelbaum * 4*f7d6f3faSMarcel Apfelbaum * Copyright (C) 2017 Red Hat Inc 5*f7d6f3faSMarcel Apfelbaum * 6*f7d6f3faSMarcel Apfelbaum * Authors: 7*f7d6f3faSMarcel Apfelbaum * Marcel Apfelbaum <marcel@redhat.com> 8*f7d6f3faSMarcel Apfelbaum * 9*f7d6f3faSMarcel Apfelbaum * This work is licensed under the terms of the GNU GPL, version 2 or later. 10*f7d6f3faSMarcel Apfelbaum * See the COPYING file in the top-level directory. 11*f7d6f3faSMarcel Apfelbaum */ 12*f7d6f3faSMarcel Apfelbaum 13*f7d6f3faSMarcel Apfelbaum #include "qemu/osdep.h" 14*f7d6f3faSMarcel Apfelbaum #include "qapi/error.h" 15*f7d6f3faSMarcel Apfelbaum #include "hw/pci/msix.h" 16*f7d6f3faSMarcel Apfelbaum #include "hw/pci/pcie_port.h" 17*f7d6f3faSMarcel Apfelbaum 18*f7d6f3faSMarcel Apfelbaum #define TYPE_GEN_PCIE_ROOT_PORT "pcie-root-port" 19*f7d6f3faSMarcel Apfelbaum 20*f7d6f3faSMarcel Apfelbaum #define GEN_PCIE_ROOT_PORT_AER_OFFSET 0x100 21*f7d6f3faSMarcel Apfelbaum #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR 1 22*f7d6f3faSMarcel Apfelbaum 23*f7d6f3faSMarcel Apfelbaum static uint8_t gen_rp_aer_vector(const PCIDevice *d) 24*f7d6f3faSMarcel Apfelbaum { 25*f7d6f3faSMarcel Apfelbaum return 0; 26*f7d6f3faSMarcel Apfelbaum } 27*f7d6f3faSMarcel Apfelbaum 28*f7d6f3faSMarcel Apfelbaum static int gen_rp_interrupts_init(PCIDevice *d, Error **errp) 29*f7d6f3faSMarcel Apfelbaum { 30*f7d6f3faSMarcel Apfelbaum int rc; 31*f7d6f3faSMarcel Apfelbaum 32*f7d6f3faSMarcel Apfelbaum rc = msix_init_exclusive_bar(d, GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR, 0); 33*f7d6f3faSMarcel Apfelbaum 34*f7d6f3faSMarcel Apfelbaum if (rc < 0) { 35*f7d6f3faSMarcel Apfelbaum assert(rc == -ENOTSUP); 36*f7d6f3faSMarcel Apfelbaum error_setg(errp, "Unable to init msix vectors"); 37*f7d6f3faSMarcel Apfelbaum } else { 38*f7d6f3faSMarcel Apfelbaum msix_vector_use(d, 0); 39*f7d6f3faSMarcel Apfelbaum } 40*f7d6f3faSMarcel Apfelbaum 41*f7d6f3faSMarcel Apfelbaum return rc; 42*f7d6f3faSMarcel Apfelbaum } 43*f7d6f3faSMarcel Apfelbaum 44*f7d6f3faSMarcel Apfelbaum static void gen_rp_interrupts_uninit(PCIDevice *d) 45*f7d6f3faSMarcel Apfelbaum { 46*f7d6f3faSMarcel Apfelbaum msix_uninit_exclusive_bar(d); 47*f7d6f3faSMarcel Apfelbaum } 48*f7d6f3faSMarcel Apfelbaum 49*f7d6f3faSMarcel Apfelbaum static const VMStateDescription vmstate_rp_dev = { 50*f7d6f3faSMarcel Apfelbaum .name = "pcie-root-port", 51*f7d6f3faSMarcel Apfelbaum .version_id = 1, 52*f7d6f3faSMarcel Apfelbaum .minimum_version_id = 1, 53*f7d6f3faSMarcel Apfelbaum .post_load = pcie_cap_slot_post_load, 54*f7d6f3faSMarcel Apfelbaum .fields = (VMStateField[]) { 55*f7d6f3faSMarcel Apfelbaum VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot), 56*f7d6f3faSMarcel Apfelbaum VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log, 57*f7d6f3faSMarcel Apfelbaum PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog), 58*f7d6f3faSMarcel Apfelbaum VMSTATE_END_OF_LIST() 59*f7d6f3faSMarcel Apfelbaum } 60*f7d6f3faSMarcel Apfelbaum }; 61*f7d6f3faSMarcel Apfelbaum 62*f7d6f3faSMarcel Apfelbaum static void gen_rp_dev_class_init(ObjectClass *klass, void *data) 63*f7d6f3faSMarcel Apfelbaum { 64*f7d6f3faSMarcel Apfelbaum DeviceClass *dc = DEVICE_CLASS(klass); 65*f7d6f3faSMarcel Apfelbaum PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 66*f7d6f3faSMarcel Apfelbaum PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); 67*f7d6f3faSMarcel Apfelbaum 68*f7d6f3faSMarcel Apfelbaum k->vendor_id = PCI_VENDOR_ID_REDHAT; 69*f7d6f3faSMarcel Apfelbaum k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_RP; 70*f7d6f3faSMarcel Apfelbaum dc->desc = "PCI Express Root Port"; 71*f7d6f3faSMarcel Apfelbaum dc->vmsd = &vmstate_rp_dev; 72*f7d6f3faSMarcel Apfelbaum rpc->aer_vector = gen_rp_aer_vector; 73*f7d6f3faSMarcel Apfelbaum rpc->interrupts_init = gen_rp_interrupts_init; 74*f7d6f3faSMarcel Apfelbaum rpc->interrupts_uninit = gen_rp_interrupts_uninit; 75*f7d6f3faSMarcel Apfelbaum rpc->aer_offset = GEN_PCIE_ROOT_PORT_AER_OFFSET; 76*f7d6f3faSMarcel Apfelbaum } 77*f7d6f3faSMarcel Apfelbaum 78*f7d6f3faSMarcel Apfelbaum static const TypeInfo gen_rp_dev_info = { 79*f7d6f3faSMarcel Apfelbaum .name = TYPE_GEN_PCIE_ROOT_PORT, 80*f7d6f3faSMarcel Apfelbaum .parent = TYPE_PCIE_ROOT_PORT, 81*f7d6f3faSMarcel Apfelbaum .class_init = gen_rp_dev_class_init, 82*f7d6f3faSMarcel Apfelbaum }; 83*f7d6f3faSMarcel Apfelbaum 84*f7d6f3faSMarcel Apfelbaum static void gen_rp_register_types(void) 85*f7d6f3faSMarcel Apfelbaum { 86*f7d6f3faSMarcel Apfelbaum type_register_static(&gen_rp_dev_info); 87*f7d6f3faSMarcel Apfelbaum } 88*f7d6f3faSMarcel Apfelbaum type_init(gen_rp_register_types) 89