2 * PCIe Data Object Exchange
4 * Copyright (C) 2021 Avery Design Systems, Inc.
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
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
;
43 /* Discard request if length does not match DoeDiscoveryReq */
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
),
55 /* Point to the requested protocol, index 0 must be Discovery */
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
);
116 /* Increment to allow for the discovery protocol */
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
;
138 * Copy the response to read mailbox buffer
139 * This might be called in self-defined handle_request() if a DOE response is
140 * required in the corresponding protocol
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
)
158 /* Only lower 18 bits are valid */
159 len
= DATA_OBJ_LEN_MASK(((DOEHeader
*)obj
)->length
);
161 /* PCIe r6.0 Table 6.29: a value of 00000h indicates 2^18 DW */
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
);
202 * Check incoming request in write_mbox for protocol format
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
;
228 * PCIe r6 DOE 6.30.1:
229 * If the number of DW transferred does not match the
230 * indicated Length for a data object, then the
231 * data object must be silently discarded.
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
);
246 * Read from DOE config space.
247 * Return false if the address not within DOE_CAP range.
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
)) {
269 /* Must return ABORT=0 and GO=0 */
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
);
281 /* Mailbox should be DW accessed */
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
];
288 /* Process Alignment */
289 shift
= addr
% DWORD_BYTE
;
290 *buf
= extract32(*buf
, shift
* 8, size
* 8);
296 * Write to DOE config space.
297 * Return if the address not within DOE_CAP range or receives an abort
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
)) {
310 /* Process Alignment */
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;
330 /* Clear interrupt bit located within the first byte */
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
:
341 /* Mailbox should be DW accessed */
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
:
355 /* Mailbox should be DW accessed */
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
: