qemu

Форк
0
/
pcie_root_port.c 
203 строки · 5.1 Кб
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 "qemu/module.h"
18
#include "hw/pci/pcie_port.h"
19
#include "hw/qdev-properties.h"
20

21
static void rp_aer_vector_update(PCIDevice *d)
22
{
23
    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
24

25
    if (rpc->aer_vector) {
26
        pcie_aer_root_set_vector(d, rpc->aer_vector(d));
27
    }
28
}
29

30
static void rp_write_config(PCIDevice *d, uint32_t address,
31
                            uint32_t val, int len)
32
{
33
    uint32_t root_cmd =
34
        pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
35
    uint16_t slt_ctl, slt_sta;
36

37
    pcie_cap_slot_get(d, &slt_ctl, &slt_sta);
38

39
    pci_bridge_write_config(d, address, val, len);
40
    rp_aer_vector_update(d);
41
    pcie_cap_slot_write_config(d, slt_ctl, slt_sta, address, val, len);
42
    pcie_aer_write_config(d, address, val, len);
43
    pcie_aer_root_write_config(d, address, val, len, root_cmd);
44
}
45

46
static void rp_reset_hold(Object *obj, ResetType type)
47
{
48
    PCIDevice *d = PCI_DEVICE(obj);
49
    DeviceState *qdev = DEVICE(obj);
50

51
    rp_aer_vector_update(d);
52
    pcie_cap_root_reset(d);
53
    pcie_cap_deverr_reset(d);
54
    pcie_cap_slot_reset(d);
55
    pcie_cap_arifwd_reset(d);
56
    pcie_acs_reset(d);
57
    pcie_aer_root_reset(d);
58
    pci_bridge_reset(qdev);
59
    pci_bridge_disable_base_limit(d);
60
}
61

62
static void rp_realize(PCIDevice *d, Error **errp)
63
{
64
    PCIEPort *p = PCIE_PORT(d);
65
    PCIESlot *s = PCIE_SLOT(d);
66
    PCIDeviceClass *dc = PCI_DEVICE_GET_CLASS(d);
67
    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
68
    int rc;
69

70
    pci_config_set_interrupt_pin(d->config, 1);
71
    if (d->cap_present & QEMU_PCIE_CAP_CXL) {
72
        pci_bridge_initfn(d, TYPE_CXL_BUS);
73
    } else {
74
        pci_bridge_initfn(d, TYPE_PCIE_BUS);
75
    }
76
    pcie_port_init_reg(d);
77

78
    rc = pci_bridge_ssvid_init(d, rpc->ssvid_offset, dc->vendor_id,
79
                               rpc->ssid, errp);
80
    if (rc < 0) {
81
        error_append_hint(errp, "Can't init SSV ID, error %d\n", rc);
82
        goto err_bridge;
83
    }
84

85
    if (rpc->interrupts_init) {
86
        rc = rpc->interrupts_init(d, errp);
87
        if (rc < 0) {
88
            goto err_bridge;
89
        }
90
    }
91

92
    rc = pcie_cap_init(d, rpc->exp_offset, PCI_EXP_TYPE_ROOT_PORT,
93
                       p->port, errp);
94
    if (rc < 0) {
95
        error_append_hint(errp, "Can't add Root Port capability, "
96
                          "error %d\n", rc);
97
        goto err_int;
98
    }
99

100
    pcie_cap_arifwd_init(d);
101
    pcie_cap_deverr_init(d);
102
    pcie_cap_slot_init(d, s);
103
    pcie_cap_root_init(d);
104

105
    pcie_chassis_create(s->chassis);
106
    rc = pcie_chassis_add_slot(s);
107
    if (rc < 0) {
108
        error_setg(errp, "Can't add chassis slot, error %d", rc);
109
        goto err_pcie_cap;
110
    }
111

112
    rc = pcie_aer_init(d, PCI_ERR_VER, rpc->aer_offset,
113
                       PCI_ERR_SIZEOF, errp);
114
    if (rc < 0) {
115
        goto err;
116
    }
117
    pcie_aer_root_init(d);
118
    rp_aer_vector_update(d);
119

120
    if (rpc->acs_offset && !s->disable_acs) {
121
        pcie_acs_init(d, rpc->acs_offset);
122
    }
123
    return;
124

125
err:
126
    pcie_chassis_del_slot(s);
127
err_pcie_cap:
128
    pcie_cap_exit(d);
129
err_int:
130
    if (rpc->interrupts_uninit) {
131
        rpc->interrupts_uninit(d);
132
    }
133
err_bridge:
134
    pci_bridge_exitfn(d);
135
}
136

137
static void rp_exit(PCIDevice *d)
138
{
139
    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
140
    PCIESlot *s = PCIE_SLOT(d);
141

142
    pcie_aer_exit(d);
143
    pcie_chassis_del_slot(s);
144
    pcie_cap_exit(d);
145
    if (rpc->interrupts_uninit) {
146
        rpc->interrupts_uninit(d);
147
    }
148
    pci_bridge_exitfn(d);
149
}
150

151
static Property rp_props[] = {
152
    DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
153
                    QEMU_PCIE_SLTCAP_PCP_BITNR, true),
154
    DEFINE_PROP_BOOL("disable-acs", PCIESlot, disable_acs, false),
155
    DEFINE_PROP_END_OF_LIST()
156
};
157

158
static void rp_instance_post_init(Object *obj)
159
{
160
    PCIESlot *s = PCIE_SLOT(obj);
161

162
    if (!s->speed) {
163
        s->speed = QEMU_PCI_EXP_LNK_2_5GT;
164
    }
165

166
    if (!s->width) {
167
        s->width = QEMU_PCI_EXP_LNK_X1;
168
    }
169
}
170

171
static void rp_class_init(ObjectClass *klass, void *data)
172
{
173
    DeviceClass *dc = DEVICE_CLASS(klass);
174
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
175
    ResettableClass *rc = RESETTABLE_CLASS(klass);
176

177
    k->config_write = rp_write_config;
178
    k->realize = rp_realize;
179
    k->exit = rp_exit;
180
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
181
    rc->phases.hold = rp_reset_hold;
182
    device_class_set_props(dc, rp_props);
183
}
184

185
static const TypeInfo rp_info = {
186
    .name          = TYPE_PCIE_ROOT_PORT,
187
    .parent        = TYPE_PCIE_SLOT,
188
    .instance_post_init = rp_instance_post_init,
189
    .class_init    = rp_class_init,
190
    .abstract      = true,
191
    .class_size = sizeof(PCIERootPortClass),
192
    .interfaces = (InterfaceInfo[]) {
193
        { INTERFACE_PCIE_DEVICE },
194
        { }
195
    },
196
};
197

198
static void rp_register_types(void)
199
{
200
    type_register_static(&rp_info);
201
}
202

203
type_init(rp_register_types)
204

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.