qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

pcie_port.c (5893B)


      1 /*
      2  * pcie_port.c
      3  *
      4  * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
      5  *                    VA Linux Systems Japan K.K.
      6  *
      7  * This program is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 2 of the License, or
     10  * (at your option) any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, see <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "hw/pci/pcie_port.h"
     23 #include "hw/qdev-properties.h"
     24 #include "qemu/module.h"
     25 #include "hw/hotplug.h"
     26 
     27 void pcie_port_init_reg(PCIDevice *d)
     28 {
     29     /* Unlike pci bridge,
     30        66MHz and fast back to back don't apply to pci express port. */
     31     pci_set_word(d->config + PCI_STATUS, 0);
     32     pci_set_word(d->config + PCI_SEC_STATUS, 0);
     33 
     34     /*
     35      * Unlike conventional pci bridge, for some bits the spec states:
     36      * Does not apply to PCI Express and must be hardwired to 0.
     37      */
     38     pci_word_test_and_clear_mask(d->wmask + PCI_BRIDGE_CONTROL,
     39                                  PCI_BRIDGE_CTL_MASTER_ABORT |
     40                                  PCI_BRIDGE_CTL_FAST_BACK |
     41                                  PCI_BRIDGE_CTL_DISCARD |
     42                                  PCI_BRIDGE_CTL_SEC_DISCARD |
     43                                  PCI_BRIDGE_CTL_DISCARD_STATUS |
     44                                  PCI_BRIDGE_CTL_DISCARD_SERR);
     45 }
     46 
     47 /**************************************************************************
     48  * (chassis number, pcie physical slot number) -> pcie slot conversion
     49  */
     50 struct PCIEChassis {
     51     uint8_t     number;
     52 
     53     QLIST_HEAD(, PCIESlot) slots;
     54     QLIST_ENTRY(PCIEChassis) next;
     55 };
     56 
     57 static QLIST_HEAD(, PCIEChassis) chassis = QLIST_HEAD_INITIALIZER(chassis);
     58 
     59 static struct PCIEChassis *pcie_chassis_find(uint8_t chassis_number)
     60 {
     61     struct PCIEChassis *c;
     62     QLIST_FOREACH(c, &chassis, next) {
     63         if (c->number == chassis_number) {
     64             break;
     65         }
     66     }
     67     return c;
     68 }
     69 
     70 void pcie_chassis_create(uint8_t chassis_number)
     71 {
     72     struct PCIEChassis *c;
     73     c = pcie_chassis_find(chassis_number);
     74     if (c) {
     75         return;
     76     }
     77     c = g_malloc0(sizeof(*c));
     78     c->number = chassis_number;
     79     QLIST_INIT(&c->slots);
     80     QLIST_INSERT_HEAD(&chassis, c, next);
     81 }
     82 
     83 static PCIESlot *pcie_chassis_find_slot_with_chassis(struct PCIEChassis *c,
     84                                                      uint8_t slot)
     85 {
     86     PCIESlot *s;
     87     QLIST_FOREACH(s, &c->slots, next) {
     88         if (s->slot == slot) {
     89             break;
     90         }
     91     }
     92     return s;
     93 }
     94 
     95 PCIESlot *pcie_chassis_find_slot(uint8_t chassis_number, uint16_t slot)
     96 {
     97     struct PCIEChassis *c;
     98     c = pcie_chassis_find(chassis_number);
     99     if (!c) {
    100         return NULL;
    101     }
    102     return pcie_chassis_find_slot_with_chassis(c, slot);
    103 }
    104 
    105 int pcie_chassis_add_slot(struct PCIESlot *slot)
    106 {
    107     struct PCIEChassis *c;
    108     c = pcie_chassis_find(slot->chassis);
    109     if (!c) {
    110         return -ENODEV;
    111     }
    112     if (pcie_chassis_find_slot_with_chassis(c, slot->slot)) {
    113         return -EBUSY;
    114     }
    115     QLIST_INSERT_HEAD(&c->slots, slot, next);
    116     return 0;
    117 }
    118 
    119 void pcie_chassis_del_slot(PCIESlot *s)
    120 {
    121     QLIST_REMOVE(s, next);
    122 }
    123 
    124 static Property pcie_port_props[] = {
    125     DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
    126     DEFINE_PROP_UINT16("aer_log_max", PCIEPort,
    127                        parent_obj.parent_obj.exp.aer_log.log_max,
    128                        PCIE_AER_LOG_MAX_DEFAULT),
    129     DEFINE_PROP_END_OF_LIST()
    130 };
    131 
    132 static void pcie_port_class_init(ObjectClass *oc, void *data)
    133 {
    134     DeviceClass *dc = DEVICE_CLASS(oc);
    135 
    136     device_class_set_props(dc, pcie_port_props);
    137 }
    138 
    139 PCIDevice *pcie_find_port_by_pn(PCIBus *bus, uint8_t pn)
    140 {
    141     int devfn;
    142 
    143     for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
    144         PCIDevice *d = bus->devices[devfn];
    145         PCIEPort *port;
    146 
    147         if (!d || !pci_is_express(d) || !d->exp.exp_cap) {
    148             continue;
    149         }
    150 
    151         if (!object_dynamic_cast(OBJECT(d), TYPE_PCIE_PORT)) {
    152             continue;
    153         }
    154 
    155         port = PCIE_PORT(d);
    156         if (port->port == pn) {
    157             return d;
    158         }
    159     }
    160 
    161     return NULL;
    162 }
    163 
    164 static const TypeInfo pcie_port_type_info = {
    165     .name = TYPE_PCIE_PORT,
    166     .parent = TYPE_PCI_BRIDGE,
    167     .instance_size = sizeof(PCIEPort),
    168     .abstract = true,
    169     .class_init = pcie_port_class_init,
    170 };
    171 
    172 static Property pcie_slot_props[] = {
    173     DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
    174     DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
    175     DEFINE_PROP_BOOL("hotplug", PCIESlot, hotplug, true),
    176     DEFINE_PROP_BOOL("x-native-hotplug", PCIESlot, native_hotplug, true),
    177     DEFINE_PROP_END_OF_LIST()
    178 };
    179 
    180 static void pcie_slot_class_init(ObjectClass *oc, void *data)
    181 {
    182     DeviceClass *dc = DEVICE_CLASS(oc);
    183     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
    184 
    185     device_class_set_props(dc, pcie_slot_props);
    186     hc->pre_plug = pcie_cap_slot_pre_plug_cb;
    187     hc->plug = pcie_cap_slot_plug_cb;
    188     hc->unplug = pcie_cap_slot_unplug_cb;
    189     hc->unplug_request = pcie_cap_slot_unplug_request_cb;
    190 }
    191 
    192 static const TypeInfo pcie_slot_type_info = {
    193     .name = TYPE_PCIE_SLOT,
    194     .parent = TYPE_PCIE_PORT,
    195     .instance_size = sizeof(PCIESlot),
    196     .abstract = true,
    197     .class_init = pcie_slot_class_init,
    198     .interfaces = (InterfaceInfo[]) {
    199         { TYPE_HOTPLUG_HANDLER },
    200         { }
    201     }
    202 };
    203 
    204 static void pcie_port_register_types(void)
    205 {
    206     type_register_static(&pcie_port_type_info);
    207     type_register_static(&pcie_slot_type_info);
    208 }
    209 
    210 type_init(pcie_port_register_types)