10
#include "qemu/osdep.h"
12
#include "qemu/error-report.h"
13
#include "qapi/error.h"
14
#include "qemu/range.h"
15
#include "hw/pci/pci.h"
16
#include "hw/pci/pcie.h"
17
#include "hw/pci/pcie_doe.h"
18
#include "hw/pci/msi.h"
19
#include "hw/pci/msix.h"
23
typedef struct DoeDiscoveryReq {
27
} QEMU_PACKED DoeDiscoveryReq;
29
typedef struct DoeDiscoveryRsp {
32
uint8_t data_obj_type;
34
} QEMU_PACKED DoeDiscoveryRsp;
36
static bool pcie_doe_discovery(DOECap *doe_cap)
38
DoeDiscoveryReq *req = pcie_doe_get_write_mbox_ptr(doe_cap);
40
uint8_t index = req->index;
44
if (pcie_doe_get_obj_len(req) <
45
DIV_ROUND_UP(sizeof(DoeDiscoveryReq), DWORD_BYTE)) {
49
rsp.header = (DOEHeader) {
50
.vendor_id = PCI_VENDOR_ID_PCI_SIG,
51
.data_obj_type = PCI_SIG_DOE_DISCOVERY,
52
.length = DIV_ROUND_UP(sizeof(DoeDiscoveryRsp), DWORD_BYTE),
57
rsp.vendor_id = PCI_VENDOR_ID_PCI_SIG;
58
rsp.data_obj_type = PCI_SIG_DOE_DISCOVERY;
60
if (index < doe_cap->protocol_num) {
61
prot = &doe_cap->protocols[index - 1];
62
rsp.vendor_id = prot->vendor_id;
63
rsp.data_obj_type = prot->data_obj_type;
65
rsp.vendor_id = 0xFFFF;
66
rsp.data_obj_type = 0xFF;
70
if (index + 1 == doe_cap->protocol_num) {
73
rsp.next_index = index + 1;
76
pcie_doe_set_rsp(doe_cap, &rsp);
81
static void pcie_doe_reset_mbox(DOECap *st)
83
st->read_mbox_idx = 0;
84
st->read_mbox_len = 0;
85
st->write_mbox_len = 0;
87
memset(st->read_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
88
memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
91
void pcie_doe_init(PCIDevice *dev, DOECap *doe_cap, uint16_t offset,
92
DOEProtocol *protocols, bool intr, uint16_t vec)
94
pcie_add_capability(dev, PCI_EXT_CAP_ID_DOE, 0x1, offset,
98
doe_cap->offset = offset;
100
if (intr && (msi_present(dev) || msix_present(dev))) {
101
doe_cap->cap.intr = intr;
102
doe_cap->cap.vec = vec;
105
doe_cap->write_mbox = g_malloc0(PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
106
doe_cap->read_mbox = g_malloc0(PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
108
pcie_doe_reset_mbox(doe_cap);
110
doe_cap->protocols = protocols;
111
for (; protocols->vendor_id; protocols++) {
112
doe_cap->protocol_num++;
114
assert(doe_cap->protocol_num < PCI_DOE_PROTOCOL_NUM_MAX);
117
doe_cap->protocol_num++;
120
void pcie_doe_fini(DOECap *doe_cap)
122
g_free(doe_cap->read_mbox);
123
g_free(doe_cap->write_mbox);
127
uint32_t pcie_doe_build_protocol(DOEProtocol *p)
129
return DATA_OBJ_BUILD_HEADER1(p->vendor_id, p->data_obj_type);
132
void *pcie_doe_get_write_mbox_ptr(DOECap *doe_cap)
134
return doe_cap->write_mbox;
142
void pcie_doe_set_rsp(DOECap *doe_cap, void *rsp)
144
uint32_t len = pcie_doe_get_obj_len(rsp);
146
memcpy(doe_cap->read_mbox + doe_cap->read_mbox_len, rsp, len * DWORD_BYTE);
147
doe_cap->read_mbox_len += len;
150
uint32_t pcie_doe_get_obj_len(void *obj)
159
len = DATA_OBJ_LEN_MASK(((DOEHeader *)obj)->length);
162
return (len) ? len : PCI_DOE_DW_SIZE_MAX;
165
static void pcie_doe_irq_assert(DOECap *doe_cap)
167
PCIDevice *dev = doe_cap->pdev;
169
if (doe_cap->cap.intr && doe_cap->ctrl.intr) {
170
if (doe_cap->status.intr) {
173
doe_cap->status.intr = 1;
175
if (msix_enabled(dev)) {
176
msix_notify(dev, doe_cap->cap.vec);
177
} else if (msi_enabled(dev)) {
178
msi_notify(dev, doe_cap->cap.vec);
183
static void pcie_doe_set_ready(DOECap *doe_cap, bool rdy)
185
doe_cap->status.ready = rdy;
188
pcie_doe_irq_assert(doe_cap);
192
static void pcie_doe_set_error(DOECap *doe_cap, bool err)
194
doe_cap->status.error = err;
197
pcie_doe_irq_assert(doe_cap);
204
static void pcie_doe_prepare_rsp(DOECap *doe_cap)
206
bool success = false;
208
bool (*handle_request)(DOECap *) = NULL;
210
if (doe_cap->status.error) {
214
if (doe_cap->write_mbox[0] ==
215
DATA_OBJ_BUILD_HEADER1(PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_DISCOVERY)) {
216
handle_request = pcie_doe_discovery;
218
for (p = 0; p < doe_cap->protocol_num - 1; p++) {
219
if (doe_cap->write_mbox[0] ==
220
pcie_doe_build_protocol(&doe_cap->protocols[p])) {
221
handle_request = doe_cap->protocols[p].handle_request;
233
if (handle_request && (doe_cap->write_mbox_len ==
234
pcie_doe_get_obj_len(pcie_doe_get_write_mbox_ptr(doe_cap)))) {
235
success = handle_request(doe_cap);
239
pcie_doe_set_ready(doe_cap, 1);
241
pcie_doe_reset_mbox(doe_cap);
249
bool pcie_doe_read_config(DOECap *doe_cap, uint32_t addr, int size,
253
uint16_t doe_offset = doe_cap->offset;
255
if (!range_covers_byte(doe_offset + PCI_EXP_DOE_CAP,
256
PCI_DOE_SIZEOF - 4, addr)) {
263
if (range_covers_byte(PCI_EXP_DOE_CAP, DWORD_BYTE, addr)) {
264
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_REG, INTR_SUPP,
266
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_REG, DOE_INTR_MSG_NUM,
268
} else if (range_covers_byte(PCI_EXP_DOE_CTRL, DWORD_BYTE, addr)) {
270
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_CONTROL, DOE_INTR_EN,
272
} else if (range_covers_byte(PCI_EXP_DOE_STATUS, DWORD_BYTE, addr)) {
273
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_BUSY,
274
doe_cap->status.busy);
275
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_INTR_STATUS,
276
doe_cap->status.intr);
277
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_ERROR,
278
doe_cap->status.error);
279
*buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DATA_OBJ_RDY,
280
doe_cap->status.ready);
282
} else if (addr == PCI_EXP_DOE_RD_DATA_MBOX && size == DWORD_BYTE) {
283
if (doe_cap->status.ready && !doe_cap->status.error) {
284
*buf = doe_cap->read_mbox[doe_cap->read_mbox_idx];
289
shift = addr % DWORD_BYTE;
290
*buf = extract32(*buf, shift * 8, size * 8);
299
void pcie_doe_write_config(DOECap *doe_cap,
300
uint32_t addr, uint32_t val, int size)
302
uint16_t doe_offset = doe_cap->offset;
305
if (!range_covers_byte(doe_offset + PCI_EXP_DOE_CAP,
306
PCI_DOE_SIZEOF - 4, addr)) {
311
shift = addr % DWORD_BYTE;
312
addr -= (doe_offset + shift);
313
val = deposit32(val, shift * 8, size * 8, val);
316
case PCI_EXP_DOE_CTRL:
317
if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_ABORT)) {
318
pcie_doe_set_ready(doe_cap, 0);
319
pcie_doe_set_error(doe_cap, 0);
320
pcie_doe_reset_mbox(doe_cap);
324
if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_GO)) {
325
pcie_doe_prepare_rsp(doe_cap);
328
if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_INTR_EN)) {
329
doe_cap->ctrl.intr = 1;
331
} else if (shift == 0) {
332
doe_cap->ctrl.intr = 0;
335
case PCI_EXP_DOE_STATUS:
336
if (FIELD_EX32(val, PCI_DOE_CAP_STATUS, DOE_INTR_STATUS)) {
337
doe_cap->status.intr = 0;
340
case PCI_EXP_DOE_RD_DATA_MBOX:
342
if (size != DWORD_BYTE) {
345
doe_cap->read_mbox_idx++;
346
if (doe_cap->read_mbox_idx == doe_cap->read_mbox_len) {
347
pcie_doe_reset_mbox(doe_cap);
348
pcie_doe_set_ready(doe_cap, 0);
349
} else if (doe_cap->read_mbox_idx > doe_cap->read_mbox_len) {
351
pcie_doe_set_error(doe_cap, 1);
354
case PCI_EXP_DOE_WR_DATA_MBOX:
356
if (size != DWORD_BYTE) {
359
doe_cap->write_mbox[doe_cap->write_mbox_len] = val;
360
doe_cap->write_mbox_len++;
362
case PCI_EXP_DOE_CAP: