~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to hw/pci-bridge/pcie_root_port.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Base class for PCI Express Root Ports
 
3
 *
 
4
 * Copyright (C) 2017 Red Hat Inc
 
5
 *
 
6
 * Authors:
 
7
 *   Marcel Apfelbaum <marcel@redhat.com>
 
8
 *
 
9
 * Most of the code was migrated from hw/pci-bridge/ioh3420.
 
10
 *
 
11
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 
12
 * See the COPYING file in the top-level directory.
 
13
 */
 
14
 
 
15
#include "qemu/osdep.h"
 
16
#include "qapi/error.h"
 
17
#include "hw/pci/pcie_port.h"
 
18
 
 
19
static void rp_aer_vector_update(PCIDevice *d)
 
20
{
 
21
    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
 
22
 
 
23
    if (rpc->aer_vector) {
 
24
        pcie_aer_root_set_vector(d, rpc->aer_vector(d));
 
25
    }
 
26
}
 
27
 
 
28
static void rp_write_config(PCIDevice *d, uint32_t address,
 
29
                            uint32_t val, int len)
 
30
{
 
31
    uint32_t root_cmd =
 
32
        pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
 
33
 
 
34
    pci_bridge_write_config(d, address, val, len);
 
35
    rp_aer_vector_update(d);
 
36
    pcie_cap_slot_write_config(d, address, val, len);
 
37
    pcie_aer_write_config(d, address, val, len);
 
38
    pcie_aer_root_write_config(d, address, val, len, root_cmd);
 
39
}
 
40
 
 
41
static void rp_reset(DeviceState *qdev)
 
42
{
 
43
    PCIDevice *d = PCI_DEVICE(qdev);
 
44
 
 
45
    rp_aer_vector_update(d);
 
46
    pcie_cap_root_reset(d);
 
47
    pcie_cap_deverr_reset(d);
 
48
    pcie_cap_slot_reset(d);
 
49
    pcie_cap_arifwd_reset(d);
 
50
    pcie_aer_root_reset(d);
 
51
    pci_bridge_reset(qdev);
 
52
    pci_bridge_disable_base_limit(d);
 
53
}
 
54
 
 
55
static void rp_realize(PCIDevice *d, Error **errp)
 
56
{
 
57
    PCIEPort *p = PCIE_PORT(d);
 
58
    PCIESlot *s = PCIE_SLOT(d);
 
59
    PCIDeviceClass *dc = PCI_DEVICE_GET_CLASS(d);
 
60
    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
 
61
    int rc;
 
62
    Error *local_err = NULL;
 
63
 
 
64
    pci_config_set_interrupt_pin(d->config, 1);
 
65
    pci_bridge_initfn(d, TYPE_PCIE_BUS);
 
66
    pcie_port_init_reg(d);
 
67
 
 
68
    rc = pci_bridge_ssvid_init(d, rpc->ssvid_offset, dc->vendor_id, rpc->ssid);
 
69
    if (rc < 0) {
 
70
        error_setg(errp, "Can't init SSV ID, error %d", rc);
 
71
        goto err_bridge;
 
72
    }
 
73
 
 
74
    if (rpc->interrupts_init) {
 
75
        rc = rpc->interrupts_init(d, &local_err);
 
76
        if (rc < 0) {
 
77
            error_propagate(errp, local_err);
 
78
            goto err_bridge;
 
79
        }
 
80
    }
 
81
 
 
82
    rc = pcie_cap_init(d, rpc->exp_offset, PCI_EXP_TYPE_ROOT_PORT, p->port);
 
83
    if (rc < 0) {
 
84
        error_setg(errp, "Can't add Root Port capability, error %d", rc);
 
85
        goto err_int;
 
86
    }
 
87
 
 
88
    pcie_cap_arifwd_init(d);
 
89
    pcie_cap_deverr_init(d);
 
90
    pcie_cap_slot_init(d, s->slot);
 
91
    pcie_cap_root_init(d);
 
92
 
 
93
    pcie_chassis_create(s->chassis);
 
94
    rc = pcie_chassis_add_slot(s);
 
95
    if (rc < 0) {
 
96
        error_setg(errp, "Can't add chassis slot, error %d", rc);
 
97
        goto err_pcie_cap;
 
98
    }
 
99
 
 
100
    rc = pcie_aer_init(d, PCI_ERR_VER, rpc->aer_offset,
 
101
                       PCI_ERR_SIZEOF, &local_err);
 
102
    if (rc < 0) {
 
103
        error_propagate(errp, local_err);
 
104
        goto err;
 
105
    }
 
106
    pcie_aer_root_init(d);
 
107
    rp_aer_vector_update(d);
 
108
 
 
109
    return;
 
110
 
 
111
err:
 
112
    pcie_chassis_del_slot(s);
 
113
err_pcie_cap:
 
114
    pcie_cap_exit(d);
 
115
err_int:
 
116
    if (rpc->interrupts_uninit) {
 
117
        rpc->interrupts_uninit(d);
 
118
    }
 
119
err_bridge:
 
120
    pci_bridge_exitfn(d);
 
121
}
 
122
 
 
123
static void rp_exit(PCIDevice *d)
 
124
{
 
125
    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
 
126
    PCIESlot *s = PCIE_SLOT(d);
 
127
 
 
128
    pcie_aer_exit(d);
 
129
    pcie_chassis_del_slot(s);
 
130
    pcie_cap_exit(d);
 
131
    if (rpc->interrupts_uninit) {
 
132
        rpc->interrupts_uninit(d);
 
133
    }
 
134
    pci_bridge_exitfn(d);
 
135
}
 
136
 
 
137
static Property rp_props[] = {
 
138
    DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
 
139
                    QEMU_PCIE_SLTCAP_PCP_BITNR, true),
 
140
    DEFINE_PROP_END_OF_LIST()
 
141
};
 
142
 
 
143
static void rp_class_init(ObjectClass *klass, void *data)
 
144
{
 
145
    DeviceClass *dc = DEVICE_CLASS(klass);
 
146
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
147
 
 
148
    k->is_express = 1;
 
149
    k->is_bridge = 1;
 
150
    k->config_write = rp_write_config;
 
151
    k->realize = rp_realize;
 
152
    k->exit = rp_exit;
 
153
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 
154
    dc->reset = rp_reset;
 
155
    dc->props = rp_props;
 
156
}
 
157
 
 
158
static const TypeInfo rp_info = {
 
159
    .name          = TYPE_PCIE_ROOT_PORT,
 
160
    .parent        = TYPE_PCIE_SLOT,
 
161
    .class_init    = rp_class_init,
 
162
    .abstract      = true,
 
163
    .class_size = sizeof(PCIERootPortClass),
 
164
};
 
165
 
 
166
static void rp_register_types(void)
 
167
{
 
168
    type_register_static(&rp_info);
 
169
}
 
170
 
 
171
type_init(rp_register_types)