qemu/hw/pci/pcie_port.c
<<
>>
Prefs
   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/hotplug.h"
  24
  25void pcie_port_init_reg(PCIDevice *d)
  26{
  27    /* Unlike pci bridge,
  28       66MHz and fast back to back don't apply to pci express port. */
  29    pci_set_word(d->config + PCI_STATUS, 0);
  30    pci_set_word(d->config + PCI_SEC_STATUS, 0);
  31
  32    /*
  33     * Unlike conventional pci bridge, for some bits the spec states:
  34     * Does not apply to PCI Express and must be hardwired to 0.
  35     */
  36    pci_word_test_and_clear_mask(d->wmask + PCI_BRIDGE_CONTROL,
  37                                 PCI_BRIDGE_CTL_MASTER_ABORT |
  38                                 PCI_BRIDGE_CTL_FAST_BACK |
  39                                 PCI_BRIDGE_CTL_DISCARD |
  40                                 PCI_BRIDGE_CTL_SEC_DISCARD |
  41                                 PCI_BRIDGE_CTL_DISCARD_STATUS |
  42                                 PCI_BRIDGE_CTL_DISCARD_SERR);
  43}
  44
  45/**************************************************************************
  46 * (chassis number, pcie physical slot number) -> pcie slot conversion
  47 */
  48struct PCIEChassis {
  49    uint8_t     number;
  50
  51    QLIST_HEAD(, PCIESlot) slots;
  52    QLIST_ENTRY(PCIEChassis) next;
  53};
  54
  55static QLIST_HEAD(, PCIEChassis) chassis = QLIST_HEAD_INITIALIZER(chassis);
  56
  57static struct PCIEChassis *pcie_chassis_find(uint8_t chassis_number)
  58{
  59    struct PCIEChassis *c;
  60    QLIST_FOREACH(c, &chassis, next) {
  61        if (c->number == chassis_number) {
  62            break;
  63        }
  64    }
  65    return c;
  66}
  67
  68void pcie_chassis_create(uint8_t chassis_number)
  69{
  70    struct PCIEChassis *c;
  71    c = pcie_chassis_find(chassis_number);
  72    if (c) {
  73        return;
  74    }
  75    c = g_malloc0(sizeof(*c));
  76    c->number = chassis_number;
  77    QLIST_INIT(&c->slots);
  78    QLIST_INSERT_HEAD(&chassis, c, next);
  79}
  80
  81static PCIESlot *pcie_chassis_find_slot_with_chassis(struct PCIEChassis *c,
  82                                                     uint8_t slot)
  83{
  84    PCIESlot *s;
  85    QLIST_FOREACH(s, &c->slots, next) {
  86        if (s->slot == slot) {
  87            break;
  88        }
  89    }
  90    return s;
  91}
  92
  93PCIESlot *pcie_chassis_find_slot(uint8_t chassis_number, uint16_t slot)
  94{
  95    struct PCIEChassis *c;
  96    c = pcie_chassis_find(chassis_number);
  97    if (!c) {
  98        return NULL;
  99    }
 100    return pcie_chassis_find_slot_with_chassis(c, slot);
 101}
 102
 103int pcie_chassis_add_slot(struct PCIESlot *slot)
 104{
 105    struct PCIEChassis *c;
 106    c = pcie_chassis_find(slot->chassis);
 107    if (!c) {
 108        return -ENODEV;
 109    }
 110    if (pcie_chassis_find_slot_with_chassis(c, slot->slot)) {
 111        return -EBUSY;
 112    }
 113    QLIST_INSERT_HEAD(&c->slots, slot, next);
 114    return 0;
 115}
 116
 117void pcie_chassis_del_slot(PCIESlot *s)
 118{
 119    QLIST_REMOVE(s, next);
 120}
 121
 122static Property pcie_port_props[] = {
 123    DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
 124    DEFINE_PROP_UINT16("aer_log_max", PCIEPort,
 125                       parent_obj.parent_obj.exp.aer_log.log_max,
 126                       PCIE_AER_LOG_MAX_DEFAULT),
 127    DEFINE_PROP_END_OF_LIST()
 128};
 129
 130static void pcie_port_class_init(ObjectClass *oc, void *data)
 131{
 132    DeviceClass *dc = DEVICE_CLASS(oc);
 133
 134    dc->props = pcie_port_props;
 135}
 136
 137static const TypeInfo pcie_port_type_info = {
 138    .name = TYPE_PCIE_PORT,
 139    .parent = TYPE_PCI_BRIDGE,
 140    .instance_size = sizeof(PCIEPort),
 141    .abstract = true,
 142    .class_init = pcie_port_class_init,
 143};
 144
 145static Property pcie_slot_props[] = {
 146    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
 147    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
 148    DEFINE_PROP_END_OF_LIST()
 149};
 150
 151static void pcie_slot_class_init(ObjectClass *oc, void *data)
 152{
 153    DeviceClass *dc = DEVICE_CLASS(oc);
 154    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
 155
 156    dc->props = pcie_slot_props;
 157    hc->plug = pcie_cap_slot_hotplug_cb;
 158    hc->unplug_request = pcie_cap_slot_hot_unplug_request_cb;
 159}
 160
 161static const TypeInfo pcie_slot_type_info = {
 162    .name = TYPE_PCIE_SLOT,
 163    .parent = TYPE_PCIE_PORT,
 164    .instance_size = sizeof(PCIESlot),
 165    .abstract = true,
 166    .class_init = pcie_slot_class_init,
 167    .interfaces = (InterfaceInfo[]) {
 168        { TYPE_HOTPLUG_HANDLER },
 169        { }
 170    }
 171};
 172
 173static void pcie_port_register_types(void)
 174{
 175    type_register_static(&pcie_port_type_info);
 176    type_register_static(&pcie_slot_type_info);
 177}
 178
 179type_init(pcie_port_register_types)
 180