10d09e41aSPaolo Bonzini /* 20d09e41aSPaolo Bonzini * pcie.h 30d09e41aSPaolo Bonzini * 40d09e41aSPaolo Bonzini * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> 50d09e41aSPaolo Bonzini * VA Linux Systems Japan K.K. 60d09e41aSPaolo Bonzini * 70d09e41aSPaolo Bonzini * This program is free software; you can redistribute it and/or modify 80d09e41aSPaolo Bonzini * it under the terms of the GNU General Public License as published by 90d09e41aSPaolo Bonzini * the Free Software Foundation; either version 2 of the License, or 100d09e41aSPaolo Bonzini * (at your option) any later version. 110d09e41aSPaolo Bonzini * 120d09e41aSPaolo Bonzini * This program is distributed in the hope that it will be useful, 130d09e41aSPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of 140d09e41aSPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 150d09e41aSPaolo Bonzini * GNU General Public License for more details. 160d09e41aSPaolo Bonzini * 170d09e41aSPaolo Bonzini * You should have received a copy of the GNU General Public License along 180d09e41aSPaolo Bonzini * with this program; if not, see <http://www.gnu.org/licenses/>. 190d09e41aSPaolo Bonzini */ 200d09e41aSPaolo Bonzini 210d09e41aSPaolo Bonzini #ifndef QEMU_PCIE_H 220d09e41aSPaolo Bonzini #define QEMU_PCIE_H 230d09e41aSPaolo Bonzini 240d09e41aSPaolo Bonzini #include "hw/hw.h" 250d09e41aSPaolo Bonzini #include "hw/pci/pci_regs.h" 260d09e41aSPaolo Bonzini #include "hw/pci/pcie_regs.h" 270d09e41aSPaolo Bonzini #include "hw/pci/pcie_aer.h" 28a66e657eSIgor Mammedov #include "hw/hotplug.h" 290d09e41aSPaolo Bonzini 300d09e41aSPaolo Bonzini typedef enum { 310d09e41aSPaolo Bonzini /* for attention and power indicator */ 320d09e41aSPaolo Bonzini PCI_EXP_HP_IND_RESERVED = PCI_EXP_SLTCTL_IND_RESERVED, 330d09e41aSPaolo Bonzini PCI_EXP_HP_IND_ON = PCI_EXP_SLTCTL_IND_ON, 340d09e41aSPaolo Bonzini PCI_EXP_HP_IND_BLINK = PCI_EXP_SLTCTL_IND_BLINK, 350d09e41aSPaolo Bonzini PCI_EXP_HP_IND_OFF = PCI_EXP_SLTCTL_IND_OFF, 360d09e41aSPaolo Bonzini } PCIExpressIndicator; 370d09e41aSPaolo Bonzini 380d09e41aSPaolo Bonzini typedef enum { 390d09e41aSPaolo Bonzini /* these bits must match the bits in Slot Control/Status registers. 400d09e41aSPaolo Bonzini * PCI_EXP_HP_EV_xxx = PCI_EXP_SLTCTL_xxxE = PCI_EXP_SLTSTA_xxx 410d09e41aSPaolo Bonzini * 420d09e41aSPaolo Bonzini * Not all the bits of slot control register match with the ones of 430d09e41aSPaolo Bonzini * slot status. Not some bits of slot status register is used to 440d09e41aSPaolo Bonzini * show status, not to report event occurrence. 450d09e41aSPaolo Bonzini * So such bits must be masked out when checking the software 460d09e41aSPaolo Bonzini * notification condition. 470d09e41aSPaolo Bonzini */ 480d09e41aSPaolo Bonzini PCI_EXP_HP_EV_ABP = PCI_EXP_SLTCTL_ABPE, 490d09e41aSPaolo Bonzini /* attention button pressed */ 500d09e41aSPaolo Bonzini PCI_EXP_HP_EV_PDC = PCI_EXP_SLTCTL_PDCE, 510d09e41aSPaolo Bonzini /* presence detect changed */ 520d09e41aSPaolo Bonzini PCI_EXP_HP_EV_CCI = PCI_EXP_SLTCTL_CCIE, 530d09e41aSPaolo Bonzini /* command completed */ 540d09e41aSPaolo Bonzini 550d09e41aSPaolo Bonzini PCI_EXP_HP_EV_SUPPORTED = PCI_EXP_HP_EV_ABP | 560d09e41aSPaolo Bonzini PCI_EXP_HP_EV_PDC | 570d09e41aSPaolo Bonzini PCI_EXP_HP_EV_CCI, 580d09e41aSPaolo Bonzini /* supported event mask */ 590d09e41aSPaolo Bonzini 600d09e41aSPaolo Bonzini /* events not listed aren't supported */ 610d09e41aSPaolo Bonzini } PCIExpressHotPlugEvent; 620d09e41aSPaolo Bonzini 630d09e41aSPaolo Bonzini struct PCIExpressDevice { 640d09e41aSPaolo Bonzini /* Offset of express capability in config space */ 650d09e41aSPaolo Bonzini uint8_t exp_cap; 660d09e41aSPaolo Bonzini 670d09e41aSPaolo Bonzini /* SLOT */ 680d09e41aSPaolo Bonzini bool hpev_notified; /* Logical AND of conditions for hot plug event. 690d09e41aSPaolo Bonzini Following 6.7.3.4: 700d09e41aSPaolo Bonzini Software Notification of Hot-Plug Events, an interrupt 710d09e41aSPaolo Bonzini is sent whenever the logical and of these conditions 720d09e41aSPaolo Bonzini transitions from false to true. */ 730d09e41aSPaolo Bonzini 740d09e41aSPaolo Bonzini /* AER */ 750d09e41aSPaolo Bonzini uint16_t aer_cap; 760d09e41aSPaolo Bonzini PCIEAERLog aer_log; 770d09e41aSPaolo Bonzini }; 780d09e41aSPaolo Bonzini 79f23b6bdcSMarcel Apfelbaum #define COMPAT_PROP_PCP "power_controller_present" 80f23b6bdcSMarcel Apfelbaum 810d09e41aSPaolo Bonzini /* PCI express capability helper functions */ 820d09e41aSPaolo Bonzini int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port); 830d09e41aSPaolo Bonzini int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset); 840d09e41aSPaolo Bonzini void pcie_cap_exit(PCIDevice *dev); 850d09e41aSPaolo Bonzini uint8_t pcie_cap_get_type(const PCIDevice *dev); 860d09e41aSPaolo Bonzini void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector); 870d09e41aSPaolo Bonzini uint8_t pcie_cap_flags_get_vector(PCIDevice *dev); 880d09e41aSPaolo Bonzini 890d09e41aSPaolo Bonzini void pcie_cap_deverr_init(PCIDevice *dev); 900d09e41aSPaolo Bonzini void pcie_cap_deverr_reset(PCIDevice *dev); 910d09e41aSPaolo Bonzini 920d09e41aSPaolo Bonzini void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot); 930d09e41aSPaolo Bonzini void pcie_cap_slot_reset(PCIDevice *dev); 940d09e41aSPaolo Bonzini void pcie_cap_slot_write_config(PCIDevice *dev, 950d09e41aSPaolo Bonzini uint32_t addr, uint32_t val, int len); 960d09e41aSPaolo Bonzini int pcie_cap_slot_post_load(void *opaque, int version_id); 970d09e41aSPaolo Bonzini void pcie_cap_slot_push_attention_button(PCIDevice *dev); 980d09e41aSPaolo Bonzini 990d09e41aSPaolo Bonzini void pcie_cap_root_init(PCIDevice *dev); 1000d09e41aSPaolo Bonzini void pcie_cap_root_reset(PCIDevice *dev); 1010d09e41aSPaolo Bonzini 1020d09e41aSPaolo Bonzini void pcie_cap_flr_init(PCIDevice *dev); 1030d09e41aSPaolo Bonzini void pcie_cap_flr_write_config(PCIDevice *dev, 1040d09e41aSPaolo Bonzini uint32_t addr, uint32_t val, int len); 1050d09e41aSPaolo Bonzini 106*821be9dbSKnut Omang /* ARI forwarding capability and control */ 107*821be9dbSKnut Omang void pcie_cap_arifwd_init(PCIDevice *dev); 108*821be9dbSKnut Omang void pcie_cap_arifwd_reset(PCIDevice *dev); 109*821be9dbSKnut Omang bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev); 1100d09e41aSPaolo Bonzini 1110d09e41aSPaolo Bonzini /* PCI express extended capability helper functions */ 1120d09e41aSPaolo Bonzini uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id); 1130d09e41aSPaolo Bonzini void pcie_add_capability(PCIDevice *dev, 1140d09e41aSPaolo Bonzini uint16_t cap_id, uint8_t cap_ver, 1150d09e41aSPaolo Bonzini uint16_t offset, uint16_t size); 1160d09e41aSPaolo Bonzini 1170d09e41aSPaolo Bonzini void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn); 1180d09e41aSPaolo Bonzini 1190d09e41aSPaolo Bonzini extern const VMStateDescription vmstate_pcie_device; 1200d09e41aSPaolo Bonzini 1210d09e41aSPaolo Bonzini #define VMSTATE_PCIE_DEVICE(_field, _state) { \ 1220d09e41aSPaolo Bonzini .name = (stringify(_field)), \ 1230d09e41aSPaolo Bonzini .size = sizeof(PCIDevice), \ 1240d09e41aSPaolo Bonzini .vmsd = &vmstate_pcie_device, \ 1250d09e41aSPaolo Bonzini .flags = VMS_STRUCT, \ 1260d09e41aSPaolo Bonzini .offset = vmstate_offset_value(_state, _field, PCIDevice), \ 1270d09e41aSPaolo Bonzini } 1280d09e41aSPaolo Bonzini 129a66e657eSIgor Mammedov void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, 130a66e657eSIgor Mammedov Error **errp); 131a66e657eSIgor Mammedov void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, 132a66e657eSIgor Mammedov Error **errp); 1330d09e41aSPaolo Bonzini #endif /* QEMU_PCIE_H */ 134