xref: /qemu/tests/qtest/ufs-test.c (revision 70ce076fa6dff60585c229a4b641b13e64bf03cf)
1 /*
2  * QTest testcase for UFS
3  *
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include "qemu/module.h"
11 #include "libqtest.h"
12 #include "libqos/qgraph.h"
13 #include "libqos/pci.h"
14 #include "scsi/constants.h"
15 #include "block/ufs.h"
16 #include "qemu/bitmap.h"
17 
18 #define DWORD_BYTE 4
19 /* Test images sizes in Bytes */
20 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
21 /* Timeout for various operations, in seconds. */
22 #define TIMEOUT_SECONDS 10
23 /* Maximum PRD entry count */
24 #define MAX_PRD_ENTRY_COUNT 10
25 #define PRD_ENTRY_DATA_SIZE 4096
26 /* Constants to build upiu */
27 #define UTP_COMMAND_DESCRIPTOR_SIZE 4096
28 #define UTP_RESPONSE_UPIU_OFFSET 1024
29 #define UTP_PRDT_UPIU_OFFSET 2048
30 #define UTRD_TEST_SLOT 0
31 #define UFS_MAX_CMD_DESC 32
32 /* Constants for MCQ */
33 #define TEST_QID 0
34 #define QUEUE_SIZE 32
35 #define UFS_MCQ_MAX_QNUM 32
36 
37 typedef struct QUfs QUfs;
38 
39 struct QUfs {
40     QOSGraphObject obj;
41     QPCIDevice dev;
42     QPCIBar bar;
43 
44     DECLARE_BITMAP(cmd_desc_bitmap, UFS_MAX_CMD_DESC);
45     uint64_t cmd_desc_addr;
46     uint64_t data_buffer_addr;
47 
48     bool enabled;
49     bool support_mcq;
50 
51     /* for legacy doorbell mode */
52     uint64_t utrlba;
53 
54     /* for mcq mode */
55     uint32_t maxq;
56     uint64_t sqlba[UFS_MCQ_MAX_QNUM];
57     uint64_t cqlba[UFS_MCQ_MAX_QNUM];
58     uint64_t sqdao[UFS_MCQ_MAX_QNUM];
59     uint64_t cqdao[UFS_MCQ_MAX_QNUM];
60 };
61 
62 static inline uint32_t ufs_rreg(QUfs *ufs, size_t offset)
63 {
64     return qpci_io_readl(&ufs->dev, ufs->bar, offset);
65 }
66 
67 static inline void ufs_wreg(QUfs *ufs, size_t offset, uint32_t value)
68 {
69     qpci_io_writel(&ufs->dev, ufs->bar, offset, value);
70 }
71 
72 static int alloc_cmd_desc_slot(QUfs *ufs)
73 {
74     int slot = find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC);
75     if (slot == UFS_MAX_CMD_DESC) {
76         g_assert_not_reached();
77     }
78     set_bit(slot, ufs->cmd_desc_bitmap);
79     return slot;
80 }
81 
82 static void release_cmd_desc_slot(QUfs *ufs, int slot)
83 {
84     if (!test_bit(slot, ufs->cmd_desc_bitmap)) {
85         g_assert_not_reached();
86     }
87     clear_bit(slot, ufs->cmd_desc_bitmap);
88 }
89 
90 static void ufs_wait_for_irq(QUfs *ufs)
91 {
92     uint64_t end_time;
93     uint32_t is;
94     /* Wait for device to reset as the linux driver does. */
95     end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
96     do {
97         qtest_clock_step(ufs->dev.bus->qts, 100);
98         is = ufs_rreg(ufs, A_IS);
99     } while (is == 0 && g_get_monotonic_time() < end_time);
100 }
101 
102 static UtpTransferReqDesc ufs_build_req_utrd(uint64_t command_desc_base_addr,
103                                              uint32_t data_direction,
104                                              uint16_t prd_table_length)
105 {
106     UtpTransferReqDesc req = { 0 };
107 
108     req.header.dword_0 =
109         cpu_to_le32(1 << 28 | data_direction | UFS_UTP_REQ_DESC_INT_CMD);
110     req.header.dword_2 = cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS);
111 
112     req.command_desc_base_addr_hi = cpu_to_le32(command_desc_base_addr >> 32);
113     req.command_desc_base_addr_lo =
114         cpu_to_le32(command_desc_base_addr & 0xffffffff);
115     req.response_upiu_offset =
116         cpu_to_le16(UTP_RESPONSE_UPIU_OFFSET / sizeof(uint32_t));
117     req.response_upiu_length = cpu_to_le16(sizeof(UtpUpiuRsp));
118     req.prd_table_offset = cpu_to_le16(UTP_PRDT_UPIU_OFFSET / sizeof(uint32_t));
119     req.prd_table_length = cpu_to_le16(prd_table_length);
120     return req;
121 }
122 
123 static enum UtpOcsCodes
124 __ufs_send_transfer_request_doorbell(QUfs *ufs, uint8_t lun,
125                                      const UtpTransferReqDesc *utrd)
126 {
127     uint64_t utrd_addr =
128         ufs->utrlba + UTRD_TEST_SLOT * sizeof(UtpTransferReqDesc);
129     UtpTransferReqDesc utrd_result;
130 
131     qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
132 
133     /* Ring the doorbell */
134     ufs_wreg(ufs, A_UTRLDBR, 1);
135     ufs_wait_for_irq(ufs);
136     g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTRCS));
137     ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTRCS, 1));
138 
139     /* Handle completed command */
140     qtest_memread(ufs->dev.bus->qts, utrd_addr, &utrd_result,
141                   sizeof(utrd_result));
142     return le32_to_cpu(utrd_result.header.dword_2) & 0xf;
143 }
144 
145 static enum UtpOcsCodes
146 __ufs_send_transfer_request_mcq(QUfs *ufs, uint8_t lun,
147                                 const UtpTransferReqDesc *utrd)
148 {
149     uint32_t sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
150     uint64_t utrd_addr = ufs->sqlba[TEST_QID] + sqtp;
151     uint32_t cqhp;
152     uint64_t cqentry_addr;
153     UfsCqEntry cqentry;
154 
155     qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
156 
157     /* Insert a new entry into the submission queue */
158     sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
159     sqtp = (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
160     ufs_wreg(ufs, ufs->sqdao[TEST_QID] + 0x4, sqtp);
161     ufs_wait_for_irq(ufs);
162     g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, CQES));
163     ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1));
164 
165     /* Handle the completed command from the completion queue */
166     cqhp = ufs_rreg(ufs, ufs->cqdao[TEST_QID]);
167     cqentry_addr = ufs->cqlba[TEST_QID] + cqhp;
168     qtest_memread(ufs->dev.bus->qts, cqentry_addr, &cqentry, sizeof(cqentry));
169     ufs_wreg(ufs, ufs->cqdao[TEST_QID], cqhp);
170 
171     return cqentry.status;
172 }
173 
174 static enum UtpOcsCodes
175 ufs_send_transfer_request_sync(QUfs *ufs, uint8_t lun,
176                                const UtpTransferReqDesc *utrd)
177 {
178     if (ufs->support_mcq) {
179         return __ufs_send_transfer_request_mcq(ufs, lun, utrd);
180     }
181 
182     return __ufs_send_transfer_request_doorbell(ufs, lun, utrd);
183 }
184 
185 static enum UtpOcsCodes ufs_send_nop_out(QUfs *ufs, UtpUpiuRsp *rsp_out)
186 {
187     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
188     uint64_t req_upiu_addr =
189         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
190     uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
191 
192     /* Build up request upiu */
193     UtpUpiuReq req_upiu = { 0 };
194     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
195     req_upiu.header.task_tag = cmd_desc_slot;
196     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
197                    sizeof(req_upiu));
198 
199     /* Build up utp transfer request descriptor */
200     UtpTransferReqDesc utrd =
201         ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
202 
203     /* Send Transfer Request */
204     enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
205 
206     qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
207     release_cmd_desc_slot(ufs, cmd_desc_slot);
208     return ret;
209 }
210 
211 static enum UtpOcsCodes ufs_send_query(QUfs *ufs, uint8_t query_function,
212                                        uint8_t query_opcode, uint8_t idn,
213                                        uint8_t index, uint8_t selector,
214                                        uint32_t attr_value, UtpUpiuRsp *rsp_out)
215 {
216     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
217     uint64_t req_upiu_addr =
218         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
219     uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
220 
221     /* Build up request upiu */
222     UtpUpiuReq req_upiu = { 0 };
223     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_QUERY_REQ;
224     req_upiu.header.query_func = query_function;
225     req_upiu.header.task_tag = cmd_desc_slot;
226     /*
227      * QEMU UFS does not currently support Write descriptor,
228      * so the value of data_segment_length is always 0.
229      */
230     req_upiu.header.data_segment_length = 0;
231     req_upiu.qr.opcode = query_opcode;
232     req_upiu.qr.idn = idn;
233     req_upiu.qr.index = index;
234     req_upiu.qr.selector = selector;
235     req_upiu.qr.value = cpu_to_be32(attr_value);
236     req_upiu.qr.length = UFS_QUERY_DESC_MAX_SIZE;
237     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
238                    sizeof(req_upiu));
239 
240     /* Build up utp transfer request descriptor */
241     UtpTransferReqDesc utrd =
242         ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
243 
244     /* Send Transfer Request */
245     enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
246 
247     qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
248     release_cmd_desc_slot(ufs, cmd_desc_slot);
249     return ret;
250 }
251 
252 static enum UtpOcsCodes
253 ufs_send_scsi_command(QUfs *ufs, uint8_t lun, const uint8_t *cdb,
254                       const uint8_t *data_in, size_t data_in_len,
255                       uint8_t *data_out, size_t data_out_len,
256                       UtpUpiuRsp *rsp_out)
257 
258 {
259     /* Build up PRDT */
260     UfshcdSgEntry entries[MAX_PRD_ENTRY_COUNT] = {
261         0,
262     };
263     uint8_t flags;
264     uint16_t prd_table_length, i;
265     uint32_t data_direction, data_len;
266     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
267     uint64_t req_upiu_addr =
268         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
269     uint64_t prdt_addr = req_upiu_addr + UTP_PRDT_UPIU_OFFSET;
270 
271     g_assert_true(data_in_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
272     g_assert_true(data_out_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
273     if (data_in_len > 0) {
274         g_assert_nonnull(data_in);
275         data_direction = UFS_UTP_HOST_TO_DEVICE;
276         data_len = data_in_len;
277         flags = UFS_UPIU_CMD_FLAGS_WRITE;
278     } else if (data_out_len > 0) {
279         g_assert_nonnull(data_out);
280         data_direction = UFS_UTP_DEVICE_TO_HOST;
281         data_len = data_out_len;
282         flags = UFS_UPIU_CMD_FLAGS_READ;
283     } else {
284         data_direction = UFS_UTP_NO_DATA_TRANSFER;
285         data_len = 0;
286         flags = UFS_UPIU_CMD_FLAGS_NONE;
287     }
288     prd_table_length = DIV_ROUND_UP(data_len, PRD_ENTRY_DATA_SIZE);
289 
290     qtest_memset(ufs->dev.bus->qts, ufs->data_buffer_addr, 0,
291                  MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
292     if (data_in_len) {
293         qtest_memwrite(ufs->dev.bus->qts, ufs->data_buffer_addr, data_in,
294                        data_in_len);
295     }
296 
297     for (i = 0; i < prd_table_length; i++) {
298         entries[i].addr =
299             cpu_to_le64(ufs->data_buffer_addr + i * sizeof(UfshcdSgEntry));
300         if (i + 1 != prd_table_length) {
301             entries[i].size = cpu_to_le32(PRD_ENTRY_DATA_SIZE - 1);
302         } else {
303             entries[i].size = cpu_to_le32(
304                 data_len - (PRD_ENTRY_DATA_SIZE * (prd_table_length - 1)) - 1);
305         }
306     }
307     qtest_memwrite(ufs->dev.bus->qts, prdt_addr, entries,
308                    prd_table_length * sizeof(UfshcdSgEntry));
309 
310     uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
311 
312     /* Build up request upiu */
313     UtpUpiuReq req_upiu = { 0 };
314     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_COMMAND;
315     req_upiu.header.flags = flags;
316     req_upiu.header.lun = lun;
317     req_upiu.header.task_tag = cmd_desc_slot;
318     req_upiu.sc.exp_data_transfer_len = cpu_to_be32(data_len);
319     memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE);
320     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
321                    sizeof(req_upiu));
322 
323     /* Build up utp transfer request descriptor */
324     UtpTransferReqDesc utrd =
325         ufs_build_req_utrd(req_upiu_addr, data_direction, prd_table_length);
326 
327     /* Send Transfer Request */
328     enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, lun, &utrd);
329 
330     qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
331     if (data_out_len) {
332         qtest_memread(ufs->dev.bus->qts, ufs->data_buffer_addr, data_out,
333                       data_out_len);
334     }
335     release_cmd_desc_slot(ufs, cmd_desc_slot);
336     return ret;
337 }
338 
339 /**
340  * Initialize Ufs host controller and logical unit.
341  * After running this function, you can make a transfer request to the UFS.
342  */
343 static void ufs_init(QUfs *ufs, QGuestAllocator *alloc)
344 {
345     uint64_t end_time;
346     uint32_t nutrs;
347     uint32_t hcs, is, ucmdarg2, cap;
348     uint32_t hce = 0, ie = 0;
349     enum UtpOcsCodes ocs;
350     UtpUpiuRsp rsp_upiu;
351 
352     ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
353     qpci_device_enable(&ufs->dev);
354 
355     /* Start host controller initialization */
356     hce = FIELD_DP32(hce, HCE, HCE, 1);
357     ufs_wreg(ufs, A_HCE, hce);
358 
359     /* Wait for device to reset */
360     end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
361     do {
362         qtest_clock_step(ufs->dev.bus->qts, 100);
363         hce = FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE);
364     } while (hce == 0 && g_get_monotonic_time() < end_time);
365     g_assert_cmpuint(hce, ==, 1);
366 
367     /* Enable interrupt */
368     ie = FIELD_DP32(ie, IE, UCCE, 1);
369     ie = FIELD_DP32(ie, IE, UHESE, 1);
370     ie = FIELD_DP32(ie, IE, UHXSE, 1);
371     ie = FIELD_DP32(ie, IE, UPMSE, 1);
372     ufs_wreg(ufs, A_IE, ie);
373 
374     /* Send DME_LINK_STARTUP uic command */
375     hcs = ufs_rreg(ufs, A_HCS);
376     g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
377 
378     ufs_wreg(ufs, A_UCMDARG1, 0);
379     ufs_wreg(ufs, A_UCMDARG2, 0);
380     ufs_wreg(ufs, A_UCMDARG3, 0);
381     ufs_wreg(ufs, A_UICCMD, UFS_UIC_CMD_DME_LINK_STARTUP);
382 
383     is = ufs_rreg(ufs, A_IS);
384     g_assert_true(FIELD_EX32(is, IS, UCCS));
385     ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UCCS, 1));
386 
387     ucmdarg2 = ufs_rreg(ufs, A_UCMDARG2);
388     g_assert_cmpuint(ucmdarg2, ==, 0);
389     is = ufs_rreg(ufs, A_IS);
390     g_assert_cmpuint(is, ==, 0);
391     hcs = ufs_rreg(ufs, A_HCS);
392     g_assert_true(FIELD_EX32(hcs, HCS, DP));
393     g_assert_true(FIELD_EX32(hcs, HCS, UTRLRDY));
394     g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
395 
396     /* Check MCQ support */
397     cap = ufs_rreg(ufs, A_CAP);
398     ufs->support_mcq = FIELD_EX32(cap, CAP, MCQS);
399 
400     /* Enable all interrupt functions */
401     ie = FIELD_DP32(ie, IE, UTRCE, 1);
402     ie = FIELD_DP32(ie, IE, UEE, 1);
403     ie = FIELD_DP32(ie, IE, UPMSE, 1);
404     ie = FIELD_DP32(ie, IE, UHXSE, 1);
405     ie = FIELD_DP32(ie, IE, UHESE, 1);
406     ie = FIELD_DP32(ie, IE, UTMRCE, 1);
407     ie = FIELD_DP32(ie, IE, UCCE, 1);
408     ie = FIELD_DP32(ie, IE, DFEE, 1);
409     ie = FIELD_DP32(ie, IE, HCFEE, 1);
410     ie = FIELD_DP32(ie, IE, SBFEE, 1);
411     ie = FIELD_DP32(ie, IE, CEFEE, 1);
412     if (ufs->support_mcq) {
413         ie = FIELD_DP32(ie, IE, CQEE, 1);
414     }
415     ufs_wreg(ufs, A_IE, ie);
416     ufs_wreg(ufs, A_UTRIACR, 0);
417 
418     /* Enable transfer request */
419     ufs->cmd_desc_addr =
420         guest_alloc(alloc, UFS_MAX_CMD_DESC * UTP_COMMAND_DESCRIPTOR_SIZE);
421     ufs->data_buffer_addr =
422         guest_alloc(alloc, MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
423 
424     if (ufs->support_mcq) {
425         uint32_t mcqcap, qid, qcfgptr, mcq_reg_offset;
426         uint32_t cqattr = 0, sqattr = 0;
427 
428         mcqcap = ufs_rreg(ufs, A_MCQCAP);
429         qcfgptr = FIELD_EX32(mcqcap, MCQCAP, QCFGPTR);
430         ufs->maxq = FIELD_EX32(mcqcap, MCQCAP, MAXQ) + 1;
431         for (qid = 0; qid < ufs->maxq; ++qid) {
432             ufs->sqlba[qid] =
433                 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
434             ufs->cqlba[qid] =
435                 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
436             mcq_reg_offset = qcfgptr * 0x200 + qid * 0x40;
437 
438             ufs_wreg(ufs, mcq_reg_offset + A_SQLBA,
439                      ufs->sqlba[qid] & 0xffffffff);
440             ufs_wreg(ufs, mcq_reg_offset + A_SQUBA, ufs->sqlba[qid] >> 32);
441             ufs_wreg(ufs, mcq_reg_offset + A_CQLBA,
442                      ufs->cqlba[qid] & 0xffffffff);
443             ufs_wreg(ufs, mcq_reg_offset + A_CQUBA, ufs->cqlba[qid] >> 32);
444 
445             /* Enable Completion Queue */
446             cqattr = FIELD_DP32(cqattr, CQATTR, CQEN, 1);
447             cqattr = FIELD_DP32(cqattr, CQATTR, SIZE,
448                                 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
449                                     DWORD_BYTE);
450             ufs_wreg(ufs, mcq_reg_offset + A_CQATTR, cqattr);
451 
452             /* Enable Submission Queue */
453             sqattr = FIELD_DP32(sqattr, SQATTR, SQEN, 1);
454             sqattr = FIELD_DP32(sqattr, SQATTR, SIZE,
455                                 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
456                                     DWORD_BYTE);
457             sqattr = FIELD_DP32(sqattr, SQATTR, CQID, qid);
458             ufs_wreg(ufs, mcq_reg_offset + A_SQATTR, sqattr);
459 
460             /* Cache head & tail pointer */
461             ufs->sqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_SQDAO);
462             ufs->cqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_CQDAO);
463         }
464     } else {
465         nutrs = FIELD_EX32(cap, CAP, NUTRS) + 1;
466         ufs->utrlba = guest_alloc(alloc, nutrs * sizeof(UtpTransferReqDesc));
467 
468         ufs_wreg(ufs, A_UTRLBA, ufs->utrlba & 0xffffffff);
469         ufs_wreg(ufs, A_UTRLBAU, ufs->utrlba >> 32);
470         ufs_wreg(ufs, A_UTRLRSR, 1);
471     }
472 
473     /* Send nop out to test transfer request */
474     ocs = ufs_send_nop_out(ufs, &rsp_upiu);
475     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
476 
477     /* Set fDeviceInit flag via query request */
478     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
479                          UFS_UPIU_QUERY_OPCODE_SET_FLAG,
480                          UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
481     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
482     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
483 
484     /* Wait for device to reset */
485     end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
486     do {
487         qtest_clock_step(ufs->dev.bus->qts, 100);
488         ocs =
489             ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
490                            UFS_UPIU_QUERY_OPCODE_READ_FLAG,
491                            UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
492         g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
493         g_assert_cmpuint(rsp_upiu.header.response, ==,
494                          UFS_COMMAND_RESULT_SUCCESS);
495     } while (be32_to_cpu(rsp_upiu.qr.value) != 0 &&
496              g_get_monotonic_time() < end_time);
497     g_assert_cmpuint(be32_to_cpu(rsp_upiu.qr.value), ==, 0);
498 
499     ufs->enabled = true;
500 }
501 
502 static void ufs_exit(QUfs *ufs, QGuestAllocator *alloc)
503 {
504     if (ufs->enabled) {
505         if (ufs->support_mcq) {
506             for (uint32_t qid = 0; qid < ufs->maxq; ++qid) {
507                 guest_free(alloc, ufs->sqlba[qid]);
508                 guest_free(alloc, ufs->cqlba[qid]);
509             }
510         } else {
511             guest_free(alloc, ufs->utrlba);
512         }
513 
514         guest_free(alloc, ufs->cmd_desc_addr);
515         guest_free(alloc, ufs->data_buffer_addr);
516     }
517 
518     qpci_iounmap(&ufs->dev, ufs->bar);
519 }
520 
521 static void *ufs_get_driver(void *obj, const char *interface)
522 {
523     QUfs *ufs = obj;
524 
525     if (!g_strcmp0(interface, "pci-device")) {
526         return &ufs->dev;
527     }
528 
529     fprintf(stderr, "%s not present in ufs\n", interface);
530     g_assert_not_reached();
531 }
532 
533 static void *ufs_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
534 {
535     QUfs *ufs = g_new0(QUfs, 1);
536     QPCIBus *bus = pci_bus;
537 
538     qpci_device_init(&ufs->dev, bus, addr);
539     ufs->obj.get_driver = ufs_get_driver;
540 
541     return &ufs->obj;
542 }
543 
544 static void ufstest_reg_read(void *obj, void *data, QGuestAllocator *alloc)
545 {
546     QUfs *ufs = obj;
547     uint32_t cap;
548 
549     ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
550     qpci_device_enable(&ufs->dev);
551 
552     cap = ufs_rreg(ufs, A_CAP);
553     g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTRS), ==, 31);
554     g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTMRS), ==, 7);
555     g_assert_cmpuint(FIELD_EX32(cap, CAP, 64AS), ==, 1);
556 
557     qpci_iounmap(&ufs->dev, ufs->bar);
558 }
559 
560 static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
561 {
562     QUfs *ufs = obj;
563 
564     uint8_t buf[4096] = { 0 };
565     const uint8_t report_luns_cdb[UFS_CDB_SIZE] = {
566         /* allocation length 4096 */
567         REPORT_LUNS, 0x00, 0x00, 0x00, 0x00, 0x00,
568         0x00,        0x00, 0x10, 0x00, 0x00, 0x00
569     };
570     const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] = {
571         TEST_UNIT_READY,
572     };
573     const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
574         REQUEST_SENSE,
575     };
576     enum UtpOcsCodes ocs;
577     UtpUpiuRsp rsp_upiu;
578 
579     ufs_init(ufs, alloc);
580 
581     /* Check REPORT_LUNS */
582     ocs = ufs_send_scsi_command(ufs, 0, report_luns_cdb, NULL, 0, buf,
583                                 sizeof(buf), &rsp_upiu);
584     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
585     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
586     /* LUN LIST LENGTH should be 8, in big endian */
587     g_assert_cmpuint(buf[3], ==, 8);
588     /* There is one logical unit whose lun is 0 */
589     g_assert_cmpuint(buf[9], ==, 0);
590 
591     /* Clear Unit Attention */
592     ocs = ufs_send_scsi_command(ufs, 0, request_sense_cdb, NULL, 0, buf,
593                                 sizeof(buf), &rsp_upiu);
594     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
595     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
596 
597     /* Check TEST_UNIT_READY */
598     ocs = ufs_send_scsi_command(ufs, 0, test_unit_ready_cdb, NULL, 0, NULL, 0,
599                                 &rsp_upiu);
600     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
601     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
602 
603     ufs_exit(ufs, alloc);
604 }
605 
606 static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
607 {
608     QUfs *ufs = obj;
609     uint8_t read_buf[4096] = { 0 };
610     uint8_t write_buf[4096] = { 0 };
611     const uint8_t read_capacity_cdb[UFS_CDB_SIZE] = {
612         /* allocation length 4096 */
613         SERVICE_ACTION_IN_16,
614         SAI_READ_CAPACITY_16,
615         0x00,
616         0x00,
617         0x00,
618         0x00,
619         0x00,
620         0x00,
621         0x00,
622         0x00,
623         0x00,
624         0x00,
625         0x10,
626         0x00,
627         0x00,
628         0x00
629     };
630     const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
631         REQUEST_SENSE,
632     };
633     const uint8_t read_cdb[UFS_CDB_SIZE] = {
634         /* READ(10) to LBA 0, transfer length 1 */
635         READ_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
636     };
637     const uint8_t write_cdb[UFS_CDB_SIZE] = {
638         /* WRITE(10) to LBA 0, transfer length 1 */
639         WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
640     };
641     uint32_t block_size;
642     enum UtpOcsCodes ocs;
643     UtpUpiuRsp rsp_upiu;
644     const int test_lun = 1;
645 
646     ufs_init(ufs, alloc);
647 
648     /* Clear Unit Attention */
649     ocs = ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, 0,
650                                 read_buf, sizeof(read_buf), &rsp_upiu);
651     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
652     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
653 
654     /* Read capacity */
655     ocs = ufs_send_scsi_command(ufs, test_lun, read_capacity_cdb, NULL, 0,
656                                 read_buf, sizeof(read_buf), &rsp_upiu);
657     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
658     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
659                      UFS_COMMAND_RESULT_SUCCESS);
660     block_size = ldl_be_p(&read_buf[8]);
661     g_assert_cmpuint(block_size, ==, 4096);
662 
663     /* Write data */
664     memset(write_buf, 0xab, block_size);
665     ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf, block_size,
666                                 NULL, 0, &rsp_upiu);
667     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
668     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
669                      UFS_COMMAND_RESULT_SUCCESS);
670 
671     /* Read data and verify */
672     ocs = ufs_send_scsi_command(ufs, test_lun, read_cdb, NULL, 0, read_buf,
673                                 block_size, &rsp_upiu);
674     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
675     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
676                      UFS_COMMAND_RESULT_SUCCESS);
677     g_assert_cmpint(memcmp(read_buf, write_buf, block_size), ==, 0);
678 
679     ufs_exit(ufs, alloc);
680 }
681 
682 static void ufstest_query_flag_request(void *obj, void *data,
683                                        QGuestAllocator *alloc)
684 {
685     QUfs *ufs = obj;
686 
687     enum UtpOcsCodes ocs;
688     UtpUpiuRsp rsp_upiu;
689     ufs_init(ufs, alloc);
690 
691     /* Read read-only flag */
692     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
693                          UFS_UPIU_QUERY_OPCODE_READ_FLAG,
694                          UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
695     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
696     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
697     g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_FLAG);
698     g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_FLAG_IDN_FDEVICEINIT);
699     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
700 
701     /* Flag Set, Clear, Toggle Test with fDeviceLifeSpanModeEn */
702     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
703                          UFS_UPIU_QUERY_OPCODE_READ_FLAG,
704                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
705                          &rsp_upiu);
706     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
707     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
708     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
709 
710     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
711                          UFS_UPIU_QUERY_OPCODE_SET_FLAG,
712                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
713                          &rsp_upiu);
714     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
715     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
716     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
717 
718     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
719                          UFS_UPIU_QUERY_OPCODE_CLEAR_FLAG,
720                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
721                          &rsp_upiu);
722     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
723     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
724     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
725 
726     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
727                          UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
728                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
729                          &rsp_upiu);
730     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
731     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
732     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
733 
734     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
735                          UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
736                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
737                          &rsp_upiu);
738     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
739     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
740     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
741 
742     /* Read Write-only Flag (Intended Failure) */
743     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
744                          UFS_UPIU_QUERY_OPCODE_READ_FLAG,
745                          UFS_QUERY_FLAG_IDN_PURGE_ENABLE, 0, 0, 0, &rsp_upiu);
746     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
747     g_assert_cmpuint(rsp_upiu.header.response, ==,
748                      UFS_QUERY_RESULT_NOT_READABLE);
749 
750     /* Write Read-Only Flag (Intended Failure) */
751     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
752                          UFS_UPIU_QUERY_OPCODE_SET_FLAG,
753                          UFS_QUERY_FLAG_IDN_BUSY_RTC, 0, 0, 0, &rsp_upiu);
754     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
755     g_assert_cmpuint(rsp_upiu.header.response, ==,
756                      UFS_QUERY_RESULT_NOT_WRITEABLE);
757 
758     ufs_exit(ufs, alloc);
759 }
760 
761 static void ufstest_query_attr_request(void *obj, void *data,
762                                        QGuestAllocator *alloc)
763 {
764     QUfs *ufs = obj;
765 
766     enum UtpOcsCodes ocs;
767     UtpUpiuRsp rsp_upiu;
768     ufs_init(ufs, alloc);
769 
770     /* Read Readable Attributes*/
771     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
772                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
773                          UFS_QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0, 0, &rsp_upiu);
774     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
775     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
776     g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_ATTR);
777     g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_ATTR_IDN_BOOT_LU_EN);
778     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
779 
780     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
781                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
782                          UFS_QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, 0, &rsp_upiu);
783     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
784     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
785     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
786 
787     /* Write Writable Attributes & Read Again */
788     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
789                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
790                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x03,
791                          &rsp_upiu);
792     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
793     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
794     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
795 
796     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
797                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
798                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0x07, &rsp_upiu);
799     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
800     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
801     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
802 
803     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
804                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
805                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
806     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
807     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
808     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
809 
810     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
811                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
812                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
813     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
814     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
815     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
816 
817     /* Write Invalid Value (Intended Error) */
818     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
819                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
820                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x10,
821                          &rsp_upiu);
822     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
823     g_assert_cmpuint(rsp_upiu.header.response, ==,
824                      UFS_QUERY_RESULT_INVALID_VALUE);
825 
826     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
827                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
828                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
829     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
830     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
831     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
832 
833     /* Read Write-Only Attribute (Intended Error) */
834     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
835                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
836                          UFS_QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, 0, &rsp_upiu);
837     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
838     g_assert_cmpuint(rsp_upiu.header.response, ==,
839                      UFS_QUERY_RESULT_NOT_READABLE);
840 
841     /* Write Read-Only Attribute (Intended Error) */
842     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
843                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
844                          UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0x01, &rsp_upiu);
845     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
846     g_assert_cmpuint(rsp_upiu.header.response, ==,
847                      UFS_QUERY_RESULT_NOT_WRITEABLE);
848 
849     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
850                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
851                          UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0, &rsp_upiu);
852     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
853     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
854     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
855 
856     /* Reset Written Attributes */
857     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
858                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
859                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
860     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
861     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
862     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
863 
864     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
865                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
866                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
867     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
868     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
869     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
870 
871     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
872                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
873                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
874     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
875     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
876     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
877 
878     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
879                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
880                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
881     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
882     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
883     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
884 
885     ufs_exit(ufs, alloc);
886 }
887 
888 static void ufstest_query_desc_request(void *obj, void *data,
889                                        QGuestAllocator *alloc)
890 {
891     QUfs *ufs = obj;
892 
893     enum UtpOcsCodes ocs;
894     UtpUpiuRsp rsp_upiu;
895     ufs_init(ufs, alloc);
896 
897     /* Write Descriptor is not supported yet */
898 
899     /* Read Device Descriptor */
900     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
901                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
902                          UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu);
903     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
904     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
905     g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_DESC);
906     g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_DESC_IDN_DEVICE);
907     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceDescriptor));
908     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_DEVICE);
909 
910     /* Read Configuration Descriptor is not supported yet*/
911 
912     /* Read Unit Descriptor */
913     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
914                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
915                          UFS_QUERY_DESC_IDN_UNIT, 0, 0, 0, &rsp_upiu);
916     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
917     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
918     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
919     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
920     g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 0);
921 
922     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
923                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
924                          UFS_QUERY_DESC_IDN_UNIT, 1, 0, 0, &rsp_upiu);
925     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
926     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
927     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
928     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
929     g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 1);
930 
931     ocs =
932         ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
933                        UFS_UPIU_QUERY_OPCODE_READ_DESC, UFS_QUERY_DESC_IDN_UNIT,
934                        UFS_UPIU_RPMB_WLUN, 0, 0, &rsp_upiu);
935     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
936     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
937     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(RpmbUnitDescriptor));
938     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
939     g_assert_cmpuint(rsp_upiu.qr.data[2], ==, UFS_UPIU_RPMB_WLUN);
940 
941     /* Read Interconnect Descriptor */
942     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
943                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
944                          UFS_QUERY_DESC_IDN_INTERCONNECT, 0, 0, 0, &rsp_upiu);
945     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
946     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
947     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(InterconnectDescriptor));
948     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_INTERCONNECT);
949 
950     /* Read String Descriptor */
951     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
952                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
953                          UFS_QUERY_DESC_IDN_STRING, 0, 0, 0, &rsp_upiu);
954     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
955     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
956     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x12);
957     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
958 
959     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
960                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
961                          UFS_QUERY_DESC_IDN_STRING, 1, 0, 0, &rsp_upiu);
962     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
963     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
964     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x22);
965     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
966 
967     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
968                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
969                          UFS_QUERY_DESC_IDN_STRING, 4, 0, 0, &rsp_upiu);
970     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
971     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
972     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x0a);
973     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
974 
975     /* Read Geometry Descriptor */
976     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
977                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
978                          UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu);
979     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
980     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
981     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(GeometryDescriptor));
982     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_GEOMETRY);
983 
984     /* Read Power Descriptor */
985     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
986                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
987                          UFS_QUERY_DESC_IDN_POWER, 0, 0, 0, &rsp_upiu);
988     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
989     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
990     g_assert_cmpuint(rsp_upiu.qr.data[0], ==,
991                      sizeof(PowerParametersDescriptor));
992     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_POWER);
993 
994     /* Read Health Descriptor */
995     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
996                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
997                          UFS_QUERY_DESC_IDN_HEALTH, 0, 0, 0, &rsp_upiu);
998     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
999     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1000     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceHealthDescriptor));
1001     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_HEALTH);
1002 
1003     /* Invalid Index (Intended Failure) */
1004     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1005                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1006                          UFS_QUERY_DESC_IDN_UNIT, 4, 0, 0, &rsp_upiu);
1007     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1008     g_assert_cmpuint(rsp_upiu.header.response, ==,
1009                      UFS_QUERY_RESULT_INVALID_INDEX);
1010 
1011     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1012                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1013                          UFS_QUERY_DESC_IDN_STRING, 5, 0, 0, &rsp_upiu);
1014     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1015     g_assert_cmpuint(rsp_upiu.header.response, ==,
1016                      UFS_QUERY_RESULT_INVALID_INDEX);
1017 
1018     /* Invalid Selector (Intended Failure) */
1019     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1020                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1021                          UFS_QUERY_DESC_IDN_DEVICE, 0, 1, 0, &rsp_upiu);
1022     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1023     g_assert_cmpuint(rsp_upiu.header.response, ==,
1024                      UFS_QUERY_RESULT_INVALID_SELECTOR);
1025 
1026     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1027                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1028                          UFS_QUERY_DESC_IDN_STRING, 0, 1, 0, &rsp_upiu);
1029     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1030     g_assert_cmpuint(rsp_upiu.header.response, ==,
1031                      UFS_QUERY_RESULT_INVALID_SELECTOR);
1032 
1033     ufs_exit(ufs, alloc);
1034 }
1035 
1036 static void drive_destroy(void *path)
1037 {
1038     unlink(path);
1039     g_free(path);
1040     qos_invalidate_command_line();
1041 }
1042 
1043 static char *drive_create(void)
1044 {
1045     int fd, ret;
1046     char *t_path;
1047 
1048     /* Create a temporary raw image */
1049     fd = g_file_open_tmp("qtest-ufs.XXXXXX", &t_path, NULL);
1050     g_assert_cmpint(fd, >=, 0);
1051     ret = ftruncate(fd, TEST_IMAGE_SIZE);
1052     g_assert_cmpint(ret, ==, 0);
1053     close(fd);
1054 
1055     g_test_queue_destroy(drive_destroy, t_path);
1056     return t_path;
1057 }
1058 
1059 static void *ufs_blk_test_setup(GString *cmd_line, void *arg)
1060 {
1061     char *tmp_path = drive_create();
1062 
1063     g_string_append_printf(cmd_line,
1064                            " -blockdev file,filename=%s,node-name=drv1 "
1065                            "-device ufs-lu,bus=ufs0,drive=drv1,lun=1 ",
1066                            tmp_path);
1067 
1068     return arg;
1069 }
1070 
1071 static void ufs_register_nodes(void)
1072 {
1073     const char *arch;
1074     QOSGraphEdgeOptions edge_opts = {
1075         .before_cmd_line = "-blockdev null-co,node-name=drv0,read-zeroes=on",
1076         .after_cmd_line = "-device ufs-lu,bus=ufs0,drive=drv0,lun=0",
1077         .extra_device_opts = "addr=04.0,id=ufs0"
1078     };
1079 
1080     QOSGraphTestOptions io_test_opts = { .before = ufs_blk_test_setup,
1081                                          .edge.extra_device_opts =
1082                                              "mcq=false,nutrs=32,nutmrs=8" };
1083 
1084     QOSGraphTestOptions mcq_test_opts = { .before = ufs_blk_test_setup,
1085                                           .edge.extra_device_opts =
1086                                               "mcq=true,mcq-maxq=1" };
1087 
1088     add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn = QPCI_DEVFN(4, 0) });
1089 
1090     qos_node_create_driver("ufs", ufs_create);
1091     qos_node_consumes("ufs", "pci-bus", &edge_opts);
1092     qos_node_produces("ufs", "pci-device");
1093 
1094     qos_add_test("reg-read", "ufs", ufstest_reg_read, NULL);
1095 
1096     /*
1097      * Check architecture
1098      * TODO: Enable ufs io tests for ppc64
1099      */
1100     arch = qtest_get_arch();
1101     if (!strcmp(arch, "ppc64")) {
1102         g_test_message("Skipping ufs io tests for ppc64");
1103         return;
1104     }
1105     qos_add_test("init", "ufs", ufstest_init, NULL);
1106     qos_add_test("legacy-read-write", "ufs", ufstest_read_write, &io_test_opts);
1107     qos_add_test("mcq-read-write", "ufs", ufstest_read_write, &mcq_test_opts);
1108     qos_add_test("query-flag", "ufs", ufstest_query_flag_request,
1109                  &io_test_opts);
1110     qos_add_test("query-attribute", "ufs", ufstest_query_attr_request,
1111                  &io_test_opts);
1112     qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request,
1113                  &io_test_opts);
1114 }
1115 
1116 libqos_init(ufs_register_nodes);
1117