contrib/elf2dmp: Fix error reporting style in addrspace.c
[qemu/armbru.git] / tests / qtest / ufs-test.c
blob95e82f94727f9e09d702c9eaf4c9eb65ab0e45a7
1 /*
2 * QTest testcase for UFS
4 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 #include "qemu/osdep.h"
10 #include "qemu/module.h"
11 #include "qemu/units.h"
12 #include "libqtest.h"
13 #include "libqos/qgraph.h"
14 #include "libqos/pci.h"
15 #include "scsi/constants.h"
16 #include "include/block/ufs.h"
18 /* Test images sizes in Bytes */
19 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
20 /* Timeout for various operations, in seconds. */
21 #define TIMEOUT_SECONDS 10
22 /* Maximum PRD entry count */
23 #define MAX_PRD_ENTRY_COUNT 10
24 #define PRD_ENTRY_DATA_SIZE 4096
25 /* Constants to build upiu */
26 #define UTP_COMMAND_DESCRIPTOR_SIZE 4096
27 #define UTP_RESPONSE_UPIU_OFFSET 1024
28 #define UTP_PRDT_UPIU_OFFSET 2048
30 typedef struct QUfs QUfs;
32 struct QUfs {
33 QOSGraphObject obj;
34 QPCIDevice dev;
35 QPCIBar bar;
37 uint64_t utrlba;
38 uint64_t utmrlba;
39 uint64_t cmd_desc_addr;
40 uint64_t data_buffer_addr;
42 bool enabled;
45 static inline uint32_t ufs_rreg(QUfs *ufs, size_t offset)
47 return qpci_io_readl(&ufs->dev, ufs->bar, offset);
50 static inline void ufs_wreg(QUfs *ufs, size_t offset, uint32_t value)
52 qpci_io_writel(&ufs->dev, ufs->bar, offset, value);
55 static void ufs_wait_for_irq(QUfs *ufs)
57 uint64_t end_time;
58 uint32_t is;
59 /* Wait for device to reset as the linux driver does. */
60 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
61 do {
62 qtest_clock_step(ufs->dev.bus->qts, 100);
63 is = ufs_rreg(ufs, A_IS);
64 } while (is == 0 && g_get_monotonic_time() < end_time);
67 static UtpTransferReqDesc ufs_build_req_utrd(uint64_t cmd_desc_addr,
68 uint8_t slot,
69 uint32_t data_direction,
70 uint16_t prd_table_length)
72 UtpTransferReqDesc req = { 0 };
73 uint64_t command_desc_base_addr =
74 cmd_desc_addr + slot * UTP_COMMAND_DESCRIPTOR_SIZE;
76 req.header.dword_0 =
77 cpu_to_le32(1 << 28 | data_direction | UFS_UTP_REQ_DESC_INT_CMD);
78 req.header.dword_2 = cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS);
80 req.command_desc_base_addr_hi = cpu_to_le32(command_desc_base_addr >> 32);
81 req.command_desc_base_addr_lo =
82 cpu_to_le32(command_desc_base_addr & 0xffffffff);
83 req.response_upiu_offset =
84 cpu_to_le16(UTP_RESPONSE_UPIU_OFFSET / sizeof(uint32_t));
85 req.response_upiu_length = cpu_to_le16(sizeof(UtpUpiuRsp));
86 req.prd_table_offset = cpu_to_le16(UTP_PRDT_UPIU_OFFSET / sizeof(uint32_t));
87 req.prd_table_length = cpu_to_le16(prd_table_length);
88 return req;
91 static void ufs_send_nop_out(QUfs *ufs, uint8_t slot,
92 UtpTransferReqDesc *utrd_out, UtpUpiuRsp *rsp_out)
94 /* Build up utp transfer request descriptor */
95 UtpTransferReqDesc utrd = ufs_build_req_utrd(ufs->cmd_desc_addr, slot,
96 UFS_UTP_NO_DATA_TRANSFER, 0);
97 uint64_t utrd_addr = ufs->utrlba + slot * sizeof(UtpTransferReqDesc);
98 uint64_t req_upiu_addr =
99 ufs->cmd_desc_addr + slot * UTP_COMMAND_DESCRIPTOR_SIZE;
100 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
101 qtest_memwrite(ufs->dev.bus->qts, utrd_addr, &utrd, sizeof(utrd));
103 /* Build up request upiu */
104 UtpUpiuReq req_upiu = { 0 };
105 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
106 req_upiu.header.task_tag = slot;
107 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
108 sizeof(req_upiu));
110 /* Ring Doorbell */
111 ufs_wreg(ufs, A_UTRLDBR, 1);
112 ufs_wait_for_irq(ufs);
113 g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTRCS));
114 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTRCS, 1));
116 qtest_memread(ufs->dev.bus->qts, utrd_addr, utrd_out, sizeof(*utrd_out));
117 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
120 static void ufs_send_query(QUfs *ufs, uint8_t slot, uint8_t query_function,
121 uint8_t query_opcode, uint8_t idn, uint8_t index,
122 UtpTransferReqDesc *utrd_out, UtpUpiuRsp *rsp_out)
124 /* Build up utp transfer request descriptor */
125 UtpTransferReqDesc utrd = ufs_build_req_utrd(ufs->cmd_desc_addr, slot,
126 UFS_UTP_NO_DATA_TRANSFER, 0);
127 uint64_t utrd_addr = ufs->utrlba + slot * sizeof(UtpTransferReqDesc);
128 uint64_t req_upiu_addr =
129 ufs->cmd_desc_addr + slot * UTP_COMMAND_DESCRIPTOR_SIZE;
130 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
131 qtest_memwrite(ufs->dev.bus->qts, utrd_addr, &utrd, sizeof(utrd));
133 /* Build up request upiu */
134 UtpUpiuReq req_upiu = { 0 };
135 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_QUERY_REQ;
136 req_upiu.header.query_func = query_function;
137 req_upiu.header.task_tag = slot;
139 * QEMU UFS does not currently support Write descriptor and Write attribute,
140 * so the value of data_segment_length is always 0.
142 req_upiu.header.data_segment_length = 0;
143 req_upiu.qr.opcode = query_opcode;
144 req_upiu.qr.idn = idn;
145 req_upiu.qr.index = index;
146 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
147 sizeof(req_upiu));
149 /* Ring Doorbell */
150 ufs_wreg(ufs, A_UTRLDBR, 1);
151 ufs_wait_for_irq(ufs);
152 g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTRCS));
153 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTRCS, 1));
155 qtest_memread(ufs->dev.bus->qts, utrd_addr, utrd_out, sizeof(*utrd_out));
156 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
159 static void ufs_send_scsi_command(QUfs *ufs, uint8_t slot, uint8_t lun,
160 const uint8_t *cdb, const uint8_t *data_in,
161 size_t data_in_len, uint8_t *data_out,
162 size_t data_out_len,
163 UtpTransferReqDesc *utrd_out,
164 UtpUpiuRsp *rsp_out)
167 /* Build up PRDT */
168 UfshcdSgEntry entries[MAX_PRD_ENTRY_COUNT] = {
171 uint8_t flags;
172 uint16_t prd_table_length, i;
173 uint32_t data_direction, data_len;
174 uint64_t req_upiu_addr =
175 ufs->cmd_desc_addr + slot * UTP_COMMAND_DESCRIPTOR_SIZE;
176 uint64_t prdt_addr = req_upiu_addr + UTP_PRDT_UPIU_OFFSET;
178 g_assert_true(data_in_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
179 g_assert_true(data_out_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
180 if (data_in_len > 0) {
181 g_assert_nonnull(data_in);
182 data_direction = UFS_UTP_HOST_TO_DEVICE;
183 data_len = data_in_len;
184 flags = UFS_UPIU_CMD_FLAGS_WRITE;
185 } else if (data_out_len > 0) {
186 g_assert_nonnull(data_out);
187 data_direction = UFS_UTP_DEVICE_TO_HOST;
188 data_len = data_out_len;
189 flags = UFS_UPIU_CMD_FLAGS_READ;
190 } else {
191 data_direction = UFS_UTP_NO_DATA_TRANSFER;
192 data_len = 0;
193 flags = UFS_UPIU_CMD_FLAGS_NONE;
195 prd_table_length = DIV_ROUND_UP(data_len, PRD_ENTRY_DATA_SIZE);
197 qtest_memset(ufs->dev.bus->qts, ufs->data_buffer_addr, 0,
198 MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
199 if (data_in_len) {
200 qtest_memwrite(ufs->dev.bus->qts, ufs->data_buffer_addr, data_in,
201 data_in_len);
204 for (i = 0; i < prd_table_length; i++) {
205 entries[i].addr =
206 cpu_to_le64(ufs->data_buffer_addr + i * sizeof(UfshcdSgEntry));
207 if (i + 1 != prd_table_length) {
208 entries[i].size = cpu_to_le32(PRD_ENTRY_DATA_SIZE - 1);
209 } else {
210 entries[i].size = cpu_to_le32(
211 data_len - (PRD_ENTRY_DATA_SIZE * (prd_table_length - 1)) - 1);
214 qtest_memwrite(ufs->dev.bus->qts, prdt_addr, entries,
215 prd_table_length * sizeof(UfshcdSgEntry));
217 /* Build up utp transfer request descriptor */
218 UtpTransferReqDesc utrd = ufs_build_req_utrd(
219 ufs->cmd_desc_addr, slot, data_direction, prd_table_length);
220 uint64_t utrd_addr = ufs->utrlba + slot * sizeof(UtpTransferReqDesc);
221 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
222 qtest_memwrite(ufs->dev.bus->qts, utrd_addr, &utrd, sizeof(utrd));
224 /* Build up request upiu */
225 UtpUpiuReq req_upiu = { 0 };
226 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_COMMAND;
227 req_upiu.header.flags = flags;
228 req_upiu.header.lun = lun;
229 req_upiu.header.task_tag = slot;
230 req_upiu.sc.exp_data_transfer_len = cpu_to_be32(data_len);
231 memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE);
232 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
233 sizeof(req_upiu));
235 /* Ring Doorbell */
236 ufs_wreg(ufs, A_UTRLDBR, 1);
237 ufs_wait_for_irq(ufs);
238 g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTRCS));
239 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTRCS, 1));
241 qtest_memread(ufs->dev.bus->qts, utrd_addr, utrd_out, sizeof(*utrd_out));
242 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
243 if (data_out_len) {
244 qtest_memread(ufs->dev.bus->qts, ufs->data_buffer_addr, data_out,
245 data_out_len);
250 * Initialize Ufs host controller and logical unit.
251 * After running this function, you can make a transfer request to the UFS.
253 static void ufs_init(QUfs *ufs, QGuestAllocator *alloc)
255 uint64_t end_time;
256 uint32_t nutrs, nutmrs;
257 uint32_t hcs, is, ucmdarg2, cap;
258 uint32_t hce = 0, ie = 0;
259 UtpTransferReqDesc utrd;
260 UtpUpiuRsp rsp_upiu;
262 ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
263 qpci_device_enable(&ufs->dev);
265 /* Start host controller initialization */
266 hce = FIELD_DP32(hce, HCE, HCE, 1);
267 ufs_wreg(ufs, A_HCE, hce);
269 /* Wait for device to reset */
270 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
271 do {
272 qtest_clock_step(ufs->dev.bus->qts, 100);
273 hce = FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE);
274 } while (hce == 0 && g_get_monotonic_time() < end_time);
275 g_assert_cmpuint(hce, ==, 1);
277 /* Enable interrupt */
278 ie = FIELD_DP32(ie, IE, UCCE, 1);
279 ie = FIELD_DP32(ie, IE, UHESE, 1);
280 ie = FIELD_DP32(ie, IE, UHXSE, 1);
281 ie = FIELD_DP32(ie, IE, UPMSE, 1);
282 ufs_wreg(ufs, A_IE, ie);
284 /* Send DME_LINK_STARTUP uic command */
285 hcs = ufs_rreg(ufs, A_HCS);
286 g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
288 ufs_wreg(ufs, A_UCMDARG1, 0);
289 ufs_wreg(ufs, A_UCMDARG2, 0);
290 ufs_wreg(ufs, A_UCMDARG3, 0);
291 ufs_wreg(ufs, A_UICCMD, UFS_UIC_CMD_DME_LINK_STARTUP);
293 is = ufs_rreg(ufs, A_IS);
294 g_assert_true(FIELD_EX32(is, IS, UCCS));
295 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UCCS, 1));
297 ucmdarg2 = ufs_rreg(ufs, A_UCMDARG2);
298 g_assert_cmpuint(ucmdarg2, ==, 0);
299 is = ufs_rreg(ufs, A_IS);
300 g_assert_cmpuint(is, ==, 0);
301 hcs = ufs_rreg(ufs, A_HCS);
302 g_assert_true(FIELD_EX32(hcs, HCS, DP));
303 g_assert_true(FIELD_EX32(hcs, HCS, UTRLRDY));
304 g_assert_true(FIELD_EX32(hcs, HCS, UTMRLRDY));
305 g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
307 /* Enable all interrupt functions */
308 ie = FIELD_DP32(ie, IE, UTRCE, 1);
309 ie = FIELD_DP32(ie, IE, UEE, 1);
310 ie = FIELD_DP32(ie, IE, UPMSE, 1);
311 ie = FIELD_DP32(ie, IE, UHXSE, 1);
312 ie = FIELD_DP32(ie, IE, UHESE, 1);
313 ie = FIELD_DP32(ie, IE, UTMRCE, 1);
314 ie = FIELD_DP32(ie, IE, UCCE, 1);
315 ie = FIELD_DP32(ie, IE, DFEE, 1);
316 ie = FIELD_DP32(ie, IE, HCFEE, 1);
317 ie = FIELD_DP32(ie, IE, SBFEE, 1);
318 ie = FIELD_DP32(ie, IE, CEFEE, 1);
319 ufs_wreg(ufs, A_IE, ie);
320 ufs_wreg(ufs, A_UTRIACR, 0);
322 /* Enable transfer request and task management request */
323 cap = ufs_rreg(ufs, A_CAP);
324 nutrs = FIELD_EX32(cap, CAP, NUTRS) + 1;
325 nutmrs = FIELD_EX32(cap, CAP, NUTMRS) + 1;
326 ufs->cmd_desc_addr =
327 guest_alloc(alloc, nutrs * UTP_COMMAND_DESCRIPTOR_SIZE);
328 ufs->data_buffer_addr =
329 guest_alloc(alloc, MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
330 ufs->utrlba = guest_alloc(alloc, nutrs * sizeof(UtpTransferReqDesc));
331 ufs->utmrlba = guest_alloc(alloc, nutmrs * sizeof(UtpTaskReqDesc));
333 ufs_wreg(ufs, A_UTRLBA, ufs->utrlba & 0xffffffff);
334 ufs_wreg(ufs, A_UTRLBAU, ufs->utrlba >> 32);
335 ufs_wreg(ufs, A_UTMRLBA, ufs->utmrlba & 0xffffffff);
336 ufs_wreg(ufs, A_UTMRLBAU, ufs->utmrlba >> 32);
337 ufs_wreg(ufs, A_UTRLRSR, 1);
338 ufs_wreg(ufs, A_UTMRLRSR, 1);
340 /* Send nop out to test transfer request */
341 ufs_send_nop_out(ufs, 0, &utrd, &rsp_upiu);
342 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
344 /* Set fDeviceInit flag via query request */
345 ufs_send_query(ufs, 0, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
346 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
347 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, &utrd, &rsp_upiu);
348 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
350 /* Wait for device to reset */
351 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
352 do {
353 qtest_clock_step(ufs->dev.bus->qts, 100);
354 ufs_send_query(ufs, 0, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
355 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
356 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, &utrd, &rsp_upiu);
357 } while (be32_to_cpu(rsp_upiu.qr.value) != 0 &&
358 g_get_monotonic_time() < end_time);
359 g_assert_cmpuint(be32_to_cpu(rsp_upiu.qr.value), ==, 0);
361 ufs->enabled = true;
364 static void ufs_exit(QUfs *ufs, QGuestAllocator *alloc)
366 if (ufs->enabled) {
367 guest_free(alloc, ufs->utrlba);
368 guest_free(alloc, ufs->utmrlba);
369 guest_free(alloc, ufs->cmd_desc_addr);
370 guest_free(alloc, ufs->data_buffer_addr);
373 qpci_iounmap(&ufs->dev, ufs->bar);
376 static void *ufs_get_driver(void *obj, const char *interface)
378 QUfs *ufs = obj;
380 if (!g_strcmp0(interface, "pci-device")) {
381 return &ufs->dev;
384 fprintf(stderr, "%s not present in ufs\n", interface);
385 g_assert_not_reached();
388 static void *ufs_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
390 QUfs *ufs = g_new0(QUfs, 1);
391 QPCIBus *bus = pci_bus;
393 qpci_device_init(&ufs->dev, bus, addr);
394 ufs->obj.get_driver = ufs_get_driver;
396 return &ufs->obj;
399 static void ufstest_reg_read(void *obj, void *data, QGuestAllocator *alloc)
401 QUfs *ufs = obj;
402 uint32_t cap;
404 ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
405 qpci_device_enable(&ufs->dev);
407 cap = ufs_rreg(ufs, A_CAP);
408 g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTRS), ==, 31);
409 g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTMRS), ==, 7);
410 g_assert_cmpuint(FIELD_EX32(cap, CAP, 64AS), ==, 1);
412 qpci_iounmap(&ufs->dev, ufs->bar);
415 static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
417 QUfs *ufs = obj;
419 uint8_t buf[4096] = { 0 };
420 const uint8_t report_luns_cdb[UFS_CDB_SIZE] = {
421 /* allocation length 4096 */
422 REPORT_LUNS, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
425 const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] = {
426 TEST_UNIT_READY,
428 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
429 REQUEST_SENSE,
431 UtpTransferReqDesc utrd;
432 UtpUpiuRsp rsp_upiu;
434 ufs_init(ufs, alloc);
436 /* Check REPORT_LUNS */
437 ufs_send_scsi_command(ufs, 0, 0, report_luns_cdb, NULL, 0, buf, sizeof(buf),
438 &utrd, &rsp_upiu);
439 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
440 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
441 /* LUN LIST LENGTH should be 8, in big endian */
442 g_assert_cmpuint(buf[3], ==, 8);
443 /* There is one logical unit whose lun is 0 */
444 g_assert_cmpuint(buf[9], ==, 0);
446 /* Clear Unit Attention */
447 ufs_send_scsi_command(ufs, 0, 0, request_sense_cdb, NULL, 0, buf,
448 sizeof(buf), &utrd, &rsp_upiu);
449 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
450 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
452 /* Check TEST_UNIT_READY */
453 ufs_send_scsi_command(ufs, 0, 0, test_unit_ready_cdb, NULL, 0, NULL, 0,
454 &utrd, &rsp_upiu);
455 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
456 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
458 ufs_exit(ufs, alloc);
461 static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
463 QUfs *ufs = obj;
464 uint8_t read_buf[4096] = { 0 };
465 uint8_t write_buf[4096] = { 0 };
466 const uint8_t read_capacity_cdb[UFS_CDB_SIZE] = {
467 /* allocation length 4096 */
468 SERVICE_ACTION_IN_16,
469 SAI_READ_CAPACITY_16,
470 0x00,
471 0x00,
472 0x00,
473 0x00,
474 0x00,
475 0x00,
476 0x00,
477 0x00,
478 0x00,
479 0x00,
480 0x10,
481 0x00,
482 0x00,
483 0x00
485 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
486 REQUEST_SENSE,
488 const uint8_t read_cdb[UFS_CDB_SIZE] = {
489 /* READ(10) to LBA 0, transfer length 1 */
490 READ_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
492 const uint8_t write_cdb[UFS_CDB_SIZE] = {
493 /* WRITE(10) to LBA 0, transfer length 1 */
494 WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
496 uint32_t block_size;
497 UtpTransferReqDesc utrd;
498 UtpUpiuRsp rsp_upiu;
499 const int test_lun = 1;
501 ufs_init(ufs, alloc);
503 /* Clear Unit Attention */
504 ufs_send_scsi_command(ufs, 0, test_lun, request_sense_cdb, NULL, 0,
505 read_buf, sizeof(read_buf), &utrd, &rsp_upiu);
506 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
507 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
509 /* Read capacity */
510 ufs_send_scsi_command(ufs, 0, test_lun, read_capacity_cdb, NULL, 0,
511 read_buf, sizeof(read_buf), &utrd, &rsp_upiu);
512 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
513 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
514 UFS_COMMAND_RESULT_SUCCESS);
515 block_size = ldl_be_p(&read_buf[8]);
516 g_assert_cmpuint(block_size, ==, 4096);
518 /* Write data */
519 memset(write_buf, 0xab, block_size);
520 ufs_send_scsi_command(ufs, 0, test_lun, write_cdb, write_buf, block_size,
521 NULL, 0, &utrd, &rsp_upiu);
522 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
523 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
524 UFS_COMMAND_RESULT_SUCCESS);
526 /* Read data and verify */
527 ufs_send_scsi_command(ufs, 0, test_lun, read_cdb, NULL, 0, read_buf,
528 block_size, &utrd, &rsp_upiu);
529 g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
530 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
531 UFS_COMMAND_RESULT_SUCCESS);
532 g_assert_cmpint(memcmp(read_buf, write_buf, block_size), ==, 0);
534 ufs_exit(ufs, alloc);
537 static void drive_destroy(void *path)
539 unlink(path);
540 g_free(path);
541 qos_invalidate_command_line();
544 static char *drive_create(void)
546 int fd, ret;
547 char *t_path;
549 /* Create a temporary raw image */
550 fd = g_file_open_tmp("qtest-ufs.XXXXXX", &t_path, NULL);
551 g_assert_cmpint(fd, >=, 0);
552 ret = ftruncate(fd, TEST_IMAGE_SIZE);
553 g_assert_cmpint(ret, ==, 0);
554 close(fd);
556 g_test_queue_destroy(drive_destroy, t_path);
557 return t_path;
560 static void *ufs_blk_test_setup(GString *cmd_line, void *arg)
562 char *tmp_path = drive_create();
564 g_string_append_printf(cmd_line,
565 " -blockdev file,filename=%s,node-name=drv1 "
566 "-device ufs-lu,bus=ufs0,drive=drv1,lun=1 ",
567 tmp_path);
569 return arg;
572 static void ufs_register_nodes(void)
574 const char *arch;
575 QOSGraphEdgeOptions edge_opts = {
576 .before_cmd_line = "-blockdev null-co,node-name=drv0,read-zeroes=on",
577 .after_cmd_line = "-device ufs-lu,bus=ufs0,drive=drv0,lun=0",
578 .extra_device_opts = "addr=04.0,id=ufs0,nutrs=32,nutmrs=8"
581 QOSGraphTestOptions io_test_opts = {
582 .before = ufs_blk_test_setup,
585 add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn = QPCI_DEVFN(4, 0) });
587 qos_node_create_driver("ufs", ufs_create);
588 qos_node_consumes("ufs", "pci-bus", &edge_opts);
589 qos_node_produces("ufs", "pci-device");
591 qos_add_test("reg-read", "ufs", ufstest_reg_read, NULL);
594 * Check architecture
595 * TODO: Enable ufs io tests for ppc64
597 arch = qtest_get_arch();
598 if (!strcmp(arch, "ppc64")) {
599 g_test_message("Skipping ufs io tests for ppc64");
600 return;
602 qos_add_test("init", "ufs", ufstest_init, NULL);
603 qos_add_test("read-write", "ufs", ufstest_read_write, &io_test_opts);
606 libqos_init(ufs_register_nodes);