ufs-next-pull-request

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEUBfYMVl8eKPZB+73EuIgTA5dtgIFAmU/DfoACgkQEuIgTA5d
 tgKZ3g/+J38LTaktLPgUb0Kg390anPkIAkqqA1QZC8lC/FRSEWpgsNBqcvAASNTl
 jj1c80k/+Dvf9Ti1lmDNkuYczCFvKNJZQ1iRHmv2wc79A01GV0Ue6xayQjjNjoKK
 SBMIsFpArmFQjR2wGlkRc8PXha1JyWrsD4iPY6ZqedEcyuueLx69XbLL37FfVbQt
 5IMnDqGkLCmrGowAjwurq2UM5IiYjeB4I5OwUgJC526zlyngXTFJimCWS6b2uUBk
 Yg1PnFffBsh11Pwmq4IZ1DAv3Bv/gFovenuatFqZrgqtfK7tEiARInIEsctu0U0a
 hPK/KojJAPF/cfMssRm1D1GCfsXM4tP2yFY/6q0wTRr9Dod8OSjlvfJR7+ez71/j
 aoY4N/nYYrZ6+pQNsPJcuBqQdtjdNUp4gUHx5qYxwwqZcHK4ubxpIvstmxceoLEX
 3PG4O1iAapc/aL12ww9bYJ2lrbKGx7ZJU/Ij8bud8tYzLheG3xaYUEhonk7DE6+e
 AXFSad5CJTIF9Duh1uAMe1sV9GxELV8MHZSalqfGOhWYp7LzUBgouEJ1gQdOQbTK
 VsLs48WQ23OjWNKyAMaXQXdFO4FVbsjIg9nQXEHNRPkUownVHNVL8zu6EsXvHfch
 u691ygt5pD100SYdcDv73xTSeqP/rxqyYdxJl4LRkv/hGWU4y78=
 =Oisg
 -----END PGP SIGNATURE-----

Merge tag 'pull-ufs-20231030' of https://gitlab.com/jeuk20.kim/qemu into staging

ufs-next-pull-request

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEUBfYMVl8eKPZB+73EuIgTA5dtgIFAmU/DfoACgkQEuIgTA5d
# tgKZ3g/+J38LTaktLPgUb0Kg390anPkIAkqqA1QZC8lC/FRSEWpgsNBqcvAASNTl
# jj1c80k/+Dvf9Ti1lmDNkuYczCFvKNJZQ1iRHmv2wc79A01GV0Ue6xayQjjNjoKK
# SBMIsFpArmFQjR2wGlkRc8PXha1JyWrsD4iPY6ZqedEcyuueLx69XbLL37FfVbQt
# 5IMnDqGkLCmrGowAjwurq2UM5IiYjeB4I5OwUgJC526zlyngXTFJimCWS6b2uUBk
# Yg1PnFffBsh11Pwmq4IZ1DAv3Bv/gFovenuatFqZrgqtfK7tEiARInIEsctu0U0a
# hPK/KojJAPF/cfMssRm1D1GCfsXM4tP2yFY/6q0wTRr9Dod8OSjlvfJR7+ez71/j
# aoY4N/nYYrZ6+pQNsPJcuBqQdtjdNUp4gUHx5qYxwwqZcHK4ubxpIvstmxceoLEX
# 3PG4O1iAapc/aL12ww9bYJ2lrbKGx7ZJU/Ij8bud8tYzLheG3xaYUEhonk7DE6+e
# AXFSad5CJTIF9Duh1uAMe1sV9GxELV8MHZSalqfGOhWYp7LzUBgouEJ1gQdOQbTK
# VsLs48WQ23OjWNKyAMaXQXdFO4FVbsjIg9nQXEHNRPkUownVHNVL8zu6EsXvHfch
# u691ygt5pD100SYdcDv73xTSeqP/rxqyYdxJl4LRkv/hGWU4y78=
# =Oisg
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 30 Oct 2023 10:59:22 JST
# gpg:                using RSA key 5017D831597C78A3D907EEF712E2204C0E5DB602
# gpg: Good signature from "Jeuk Kim <jeuk20.kim@samsung.com>" [unknown]
# gpg:                 aka "Jeuk Kim <jeuk20.kim@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 5017 D831 597C 78A3 D907  EEF7 12E2 204C 0E5D B602

* tag 'pull-ufs-20231030' of https://gitlab.com/jeuk20.kim/qemu:
  hw/ufs: Modify lu.c to share codes with SCSI subsystem

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
master
Stefan Hajnoczi 2023-10-31 07:11:23 +09:00
commit 235fe6d06e
6 changed files with 334 additions and 1479 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,31 +12,6 @@ ufs_exec_scsi_cmd(uint32_t slot, uint8_t lun, uint8_t opcode) "slot %"PRIu32", l
ufs_exec_query_cmd(uint32_t slot, uint8_t opcode) "slot %"PRIu32", opcode 0x%"PRIx8""
ufs_process_uiccmd(uint32_t uiccmd, uint32_t ucmdarg1, uint32_t ucmdarg2, uint32_t ucmdarg3) "uiccmd 0x%"PRIx32", ucmdarg1 0x%"PRIx32", ucmdarg2 0x%"PRIx32", ucmdarg3 0x%"PRIx32""
# lu.c
ufs_scsi_check_condition(uint32_t tag, uint8_t key, uint8_t asc, uint8_t ascq) "Command complete tag=0x%x sense=%d/%d/%d"
ufs_scsi_read_complete(uint32_t tag, size_t size) "Data ready tag=0x%x len=%zd"
ufs_scsi_read_data_count(uint32_t sector_count) "Read sector_count=%d"
ufs_scsi_read_data_invalid(void) "Data transfer direction invalid"
ufs_scsi_write_complete_noio(uint32_t tag, size_t size) "Write complete tag=0x%x more=%zd"
ufs_scsi_write_data_invalid(void) "Data transfer direction invalid"
ufs_scsi_emulate_vpd_page_00(size_t xfer) "Inquiry EVPD[Supported pages] buffer size %zd"
ufs_scsi_emulate_vpd_page_80_not_supported(void) "Inquiry EVPD[Serial number] not supported"
ufs_scsi_emulate_vpd_page_80(size_t xfer) "Inquiry EVPD[Serial number] buffer size %zd"
ufs_scsi_emulate_vpd_page_87(size_t xfer) "Inquiry EVPD[Mode Page Policy] buffer size %zd"
ufs_scsi_emulate_mode_sense(int cmd, int page, size_t xfer, int control) "Mode Sense(%d) (page %d, xfer %zd, page_control %d)"
ufs_scsi_emulate_read_data(int buflen) "Read buf_len=%d"
ufs_scsi_emulate_write_data(int buflen) "Write buf_len=%d"
ufs_scsi_emulate_command_START_STOP(void) "START STOP UNIT"
ufs_scsi_emulate_command_FORMAT_UNIT(void) "FORMAT UNIT"
ufs_scsi_emulate_command_SEND_DIAGNOSTIC(void) "SEND DIAGNOSTIC"
ufs_scsi_emulate_command_SAI_16(void) "SAI READ CAPACITY(16)"
ufs_scsi_emulate_command_SAI_unsupported(void) "Unsupported Service Action In"
ufs_scsi_emulate_command_MODE_SELECT_10(size_t xfer) "Mode Select(10) (len %zd)"
ufs_scsi_emulate_command_VERIFY(int bytchk) "Verify (bytchk %d)"
ufs_scsi_emulate_command_UNKNOWN(int cmd, const char *name) "Unknown SCSI command (0x%2.2x=%s)"
ufs_scsi_dma_command_READ(uint64_t lba, uint32_t len) "Read (block %" PRIu64 ", count %u)"
ufs_scsi_dma_command_WRITE(uint64_t lba, int len) "Write (block %" PRIu64 ", count %u)"
# error condition
ufs_err_dma_read_utrd(uint32_t slot, uint64_t addr) "failed to read utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64""
ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req upiu. UTRLDBR slot %"PRIu32", request upiu addr %"PRIu64""

View File

@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "migration/vmstate.h"
#include "scsi/constants.h"
#include "trace.h"
#include "ufs.h"
@ -62,8 +63,6 @@ static MemTxResult ufs_addr_write(UfsHc *u, hwaddr addr, const void *buf,
return pci_dma_write(PCI_DEVICE(u), addr, buf, size);
}
static void ufs_complete_req(UfsRequest *req, UfsReqResult req_result);
static inline hwaddr ufs_get_utrd_addr(UfsHc *u, uint32_t slot)
{
hwaddr utrl_base_addr = (((hwaddr)u->reg.utrlbau) << 32) + u->reg.utrlba;
@ -163,11 +162,13 @@ static MemTxResult ufs_dma_read_prdt(UfsRequest *req)
req->sg = g_malloc0(sizeof(QEMUSGList));
pci_dma_sglist_init(req->sg, PCI_DEVICE(u), prdt_len);
req->data_len = 0;
for (uint16_t i = 0; i < prdt_len; ++i) {
hwaddr data_dma_addr = le64_to_cpu(prd_entries[i].addr);
uint32_t data_byte_count = le32_to_cpu(prd_entries[i].size) + 1;
qemu_sglist_add(req->sg, data_dma_addr, data_byte_count);
req->data_len += data_byte_count;
}
return MEMTX_OK;
}
@ -433,23 +434,10 @@ static const MemoryRegionOps ufs_mmio_ops = {
},
};
static QEMUSGList *ufs_get_sg_list(SCSIRequest *scsi_req)
{
UfsRequest *req = scsi_req->hba_private;
return req->sg;
}
static void ufs_build_upiu_sense_data(UfsRequest *req, SCSIRequest *scsi_req)
{
req->rsp_upiu.sr.sense_data_len = cpu_to_be16(scsi_req->sense_len);
assert(scsi_req->sense_len <= SCSI_SENSE_LEN);
memcpy(req->rsp_upiu.sr.sense_data, scsi_req->sense, scsi_req->sense_len);
}
static void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type,
uint8_t flags, uint8_t response,
uint8_t scsi_status,
uint16_t data_segment_length)
void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type, uint8_t flags,
uint8_t response, uint8_t scsi_status,
uint16_t data_segment_length)
{
memcpy(&req->rsp_upiu.header, &req->req_upiu.header, sizeof(UtpUpiuHeader));
req->rsp_upiu.header.trans_type = trans_type;
@ -459,96 +447,38 @@ static void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type,
req->rsp_upiu.header.data_segment_length = cpu_to_be16(data_segment_length);
}
static void ufs_scsi_command_complete(SCSIRequest *scsi_req, size_t resid)
{
UfsRequest *req = scsi_req->hba_private;
int16_t status = scsi_req->status;
uint32_t expected_len = be32_to_cpu(req->req_upiu.sc.exp_data_transfer_len);
uint32_t transfered_len = scsi_req->cmd.xfer - resid;
uint8_t flags = 0, response = UFS_COMMAND_RESULT_SUCESS;
uint16_t data_segment_length;
if (expected_len > transfered_len) {
req->rsp_upiu.sr.residual_transfer_count =
cpu_to_be32(expected_len - transfered_len);
flags |= UFS_UPIU_FLAG_UNDERFLOW;
} else if (expected_len < transfered_len) {
req->rsp_upiu.sr.residual_transfer_count =
cpu_to_be32(transfered_len - expected_len);
flags |= UFS_UPIU_FLAG_OVERFLOW;
}
if (status != 0) {
ufs_build_upiu_sense_data(req, scsi_req);
response = UFS_COMMAND_RESULT_FAIL;
}
data_segment_length = cpu_to_be16(scsi_req->sense_len +
sizeof(req->rsp_upiu.sr.sense_data_len));
ufs_build_upiu_header(req, UFS_UPIU_TRANSACTION_RESPONSE, flags, response,
status, data_segment_length);
ufs_complete_req(req, UFS_REQUEST_SUCCESS);
scsi_req->hba_private = NULL;
scsi_req_unref(scsi_req);
}
static const struct SCSIBusInfo ufs_scsi_info = {
.tcq = true,
.max_target = 0,
.max_lun = UFS_MAX_LUS,
.max_channel = 0,
.get_sg_list = ufs_get_sg_list,
.complete = ufs_scsi_command_complete,
};
static UfsReqResult ufs_exec_scsi_cmd(UfsRequest *req)
{
UfsHc *u = req->hc;
uint8_t lun = req->req_upiu.header.lun;
uint8_t task_tag = req->req_upiu.header.task_tag;
SCSIDevice *dev = NULL;
UfsLu *lu = NULL;
trace_ufs_exec_scsi_cmd(req->slot, lun, req->req_upiu.sc.cdb[0]);
if (!is_wlun(lun)) {
if (lun >= u->device_desc.number_lu) {
trace_ufs_err_scsi_cmd_invalid_lun(lun);
return UFS_REQUEST_FAIL;
} else if (u->lus[lun] == NULL) {
trace_ufs_err_scsi_cmd_invalid_lun(lun);
return UFS_REQUEST_FAIL;
}
if (!is_wlun(lun) && (lun >= UFS_MAX_LUS || u->lus[lun] == NULL)) {
trace_ufs_err_scsi_cmd_invalid_lun(lun);
return UFS_REQUEST_FAIL;
}
switch (lun) {
case UFS_UPIU_REPORT_LUNS_WLUN:
dev = &u->report_wlu->qdev;
lu = &u->report_wlu;
break;
case UFS_UPIU_UFS_DEVICE_WLUN:
dev = &u->dev_wlu->qdev;
lu = &u->dev_wlu;
break;
case UFS_UPIU_BOOT_WLUN:
dev = &u->boot_wlu->qdev;
lu = &u->boot_wlu;
break;
case UFS_UPIU_RPMB_WLUN:
dev = &u->rpmb_wlu->qdev;
lu = &u->rpmb_wlu;
break;
default:
dev = &u->lus[lun]->qdev;
lu = u->lus[lun];
}
SCSIRequest *scsi_req = scsi_req_new(
dev, task_tag, lun, req->req_upiu.sc.cdb, UFS_CDB_SIZE, req);
uint32_t len = scsi_req_enqueue(scsi_req);
if (len) {
scsi_req_continue(scsi_req);
}
return UFS_REQUEST_NO_COMPLETE;
return lu->scsi_op(lu, req);
}
static UfsReqResult ufs_exec_nop_cmd(UfsRequest *req)
@ -1137,7 +1067,7 @@ static void ufs_process_req(void *opaque)
}
}
static void ufs_complete_req(UfsRequest *req, UfsReqResult req_result)
void ufs_complete_req(UfsRequest *req, UfsReqResult req_result)
{
UfsHc *u = req->hc;
assert(req->state == UFS_REQUEST_RUNNING);
@ -1159,6 +1089,7 @@ static void ufs_clear_req(UfsRequest *req)
qemu_sglist_destroy(req->sg);
g_free(req->sg);
req->sg = NULL;
req->data_len = 0;
}
memset(&req->utrd, 0, sizeof(req->utrd));
@ -1317,28 +1248,6 @@ static void ufs_init_hc(UfsHc *u)
u->flags.permanently_disable_fw_update = 1;
}
static bool ufs_init_wlu(UfsHc *u, UfsWLu **wlu, uint8_t wlun, Error **errp)
{
UfsWLu *new_wlu = UFSWLU(qdev_new(TYPE_UFS_WLU));
qdev_prop_set_uint32(DEVICE(new_wlu), "lun", wlun);
/*
* The well-known lu shares the same bus as the normal lu. If the well-known
* lu writes the same channel value as the normal lu, the report will be
* made not only for the normal lu but also for the well-known lu at
* REPORT_LUN time. To prevent this, the channel value of normal lu is fixed
* to 0 and the channel value of well-known lu is fixed to 1.
*/
qdev_prop_set_uint32(DEVICE(new_wlu), "channel", 1);
if (!qdev_realize_and_unref(DEVICE(new_wlu), BUS(&u->bus), errp)) {
return false;
}
*wlu = new_wlu;
return true;
}
static void ufs_realize(PCIDevice *pci_dev, Error **errp)
{
UfsHc *u = UFS(pci_dev);
@ -1349,53 +1258,21 @@ static void ufs_realize(PCIDevice *pci_dev, Error **errp)
qbus_init(&u->bus, sizeof(UfsBus), TYPE_UFS_BUS, &pci_dev->qdev,
u->parent_obj.qdev.id);
u->bus.parent_bus.info = &ufs_scsi_info;
ufs_init_state(u);
ufs_init_hc(u);
ufs_init_pci(u, pci_dev);
if (!ufs_init_wlu(u, &u->report_wlu, UFS_UPIU_REPORT_LUNS_WLUN, errp)) {
return;
}
if (!ufs_init_wlu(u, &u->dev_wlu, UFS_UPIU_UFS_DEVICE_WLUN, errp)) {
return;
}
if (!ufs_init_wlu(u, &u->boot_wlu, UFS_UPIU_BOOT_WLUN, errp)) {
return;
}
if (!ufs_init_wlu(u, &u->rpmb_wlu, UFS_UPIU_RPMB_WLUN, errp)) {
return;
}
ufs_init_wlu(&u->report_wlu, UFS_UPIU_REPORT_LUNS_WLUN);
ufs_init_wlu(&u->dev_wlu, UFS_UPIU_UFS_DEVICE_WLUN);
ufs_init_wlu(&u->boot_wlu, UFS_UPIU_BOOT_WLUN);
ufs_init_wlu(&u->rpmb_wlu, UFS_UPIU_RPMB_WLUN);
}
static void ufs_exit(PCIDevice *pci_dev)
{
UfsHc *u = UFS(pci_dev);
if (u->dev_wlu) {
object_unref(OBJECT(u->dev_wlu));
u->dev_wlu = NULL;
}
if (u->report_wlu) {
object_unref(OBJECT(u->report_wlu));
u->report_wlu = NULL;
}
if (u->rpmb_wlu) {
object_unref(OBJECT(u->rpmb_wlu));
u->rpmb_wlu = NULL;
}
if (u->boot_wlu) {
object_unref(OBJECT(u->boot_wlu));
u->boot_wlu = NULL;
}
qemu_bh_delete(u->doorbell_bh);
qemu_bh_delete(u->complete_bh);
@ -1437,43 +1314,18 @@ static void ufs_class_init(ObjectClass *oc, void *data)
static bool ufs_bus_check_address(BusState *qbus, DeviceState *qdev,
Error **errp)
{
SCSIDevice *dev = SCSI_DEVICE(qdev);
UfsBusClass *ubc = UFS_BUS_GET_CLASS(qbus);
UfsHc *u = UFS(qbus->parent);
if (strcmp(object_get_typename(OBJECT(dev)), TYPE_UFS_WLU) == 0) {
if (dev->lun != UFS_UPIU_REPORT_LUNS_WLUN &&
dev->lun != UFS_UPIU_UFS_DEVICE_WLUN &&
dev->lun != UFS_UPIU_BOOT_WLUN && dev->lun != UFS_UPIU_RPMB_WLUN) {
error_setg(errp, "bad well-known lun: %d", dev->lun);
return false;
}
if ((dev->lun == UFS_UPIU_REPORT_LUNS_WLUN && u->report_wlu != NULL) ||
(dev->lun == UFS_UPIU_UFS_DEVICE_WLUN && u->dev_wlu != NULL) ||
(dev->lun == UFS_UPIU_BOOT_WLUN && u->boot_wlu != NULL) ||
(dev->lun == UFS_UPIU_RPMB_WLUN && u->rpmb_wlu != NULL)) {
error_setg(errp, "well-known lun %d already exists", dev->lun);
return false;
}
return true;
}
if (strcmp(object_get_typename(OBJECT(dev)), TYPE_UFS_LU) != 0) {
if (strcmp(object_get_typename(OBJECT(qdev)), TYPE_UFS_LU) != 0) {
error_setg(errp, "%s cannot be connected to ufs-bus",
object_get_typename(OBJECT(dev)));
object_get_typename(OBJECT(qdev)));
return false;
}
return ubc->parent_check_address(qbus, qdev, errp);
return true;
}
static void ufs_bus_class_init(ObjectClass *class, void *data)
{
BusClass *bc = BUS_CLASS(class);
UfsBusClass *ubc = UFS_BUS_CLASS(class);
ubc->parent_check_address = bc->check_address;
bc->check_address = ufs_bus_check_address;
}
@ -1487,7 +1339,7 @@ static const TypeInfo ufs_info = {
static const TypeInfo ufs_bus_info = {
.name = TYPE_UFS_BUS,
.parent = TYPE_SCSI_BUS,
.parent = TYPE_BUS,
.class_init = ufs_bus_class_init,
.class_size = sizeof(UfsBusClass),
.instance_size = sizeof(UfsBus),

View File

@ -16,7 +16,8 @@
#include "block/ufs.h"
#define UFS_MAX_LUS 32
#define UFS_BLOCK_SIZE 4096
#define UFS_BLOCK_SIZE_SHIFT 12
#define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SIZE_SHIFT)
typedef struct UfsBusClass {
BusClass parent_class;
@ -24,7 +25,7 @@ typedef struct UfsBusClass {
} UfsBusClass;
typedef struct UfsBus {
SCSIBus parent_bus;
BusState parent_bus;
} UfsBus;
#define TYPE_UFS_BUS "ufs-bus"
@ -55,19 +56,22 @@ typedef struct UfsRequest {
/* for scsi command */
QEMUSGList *sg;
uint32_t data_len;
} UfsRequest;
struct UfsLu;
typedef UfsReqResult (*UfsScsiOp)(struct UfsLu *, UfsRequest *);
typedef struct UfsLu {
SCSIDevice qdev;
DeviceState qdev;
uint8_t lun;
UnitDescriptor unit_desc;
SCSIBus bus;
SCSIDevice *scsi_dev;
BlockConf conf;
UfsScsiOp scsi_op;
} UfsLu;
typedef struct UfsWLu {
SCSIDevice qdev;
uint8_t lun;
} UfsWLu;
typedef struct UfsParams {
char *serial;
uint8_t nutrs; /* Number of UTP Transfer Request Slots */
@ -84,10 +88,10 @@ typedef struct UfsHc {
UfsRequest *req_list;
UfsLu *lus[UFS_MAX_LUS];
UfsWLu *report_wlu;
UfsWLu *dev_wlu;
UfsWLu *boot_wlu;
UfsWLu *rpmb_wlu;
UfsLu report_wlu;
UfsLu dev_wlu;
UfsLu boot_wlu;
UfsLu rpmb_wlu;
DeviceDescriptor device_desc;
GeometryDescriptor geometry_desc;
Attributes attributes;
@ -104,9 +108,6 @@ typedef struct UfsHc {
#define TYPE_UFS_LU "ufs-lu"
#define UFSLU(obj) OBJECT_CHECK(UfsLu, (obj), TYPE_UFS_LU)
#define TYPE_UFS_WLU "ufs-wlu"
#define UFSWLU(obj) OBJECT_CHECK(UfsWLu, (obj), TYPE_UFS_WLU)
typedef enum UfsQueryFlagPerm {
UFS_QUERY_FLAG_NONE = 0x0,
UFS_QUERY_FLAG_READ = 0x1,
@ -128,4 +129,9 @@ static inline bool is_wlun(uint8_t lun)
lun == UFS_UPIU_RPMB_WLUN);
}
void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type, uint8_t flags,
uint8_t response, uint8_t scsi_status,
uint16_t data_segment_length);
void ufs_complete_req(UfsRequest *req, UfsReqResult req_result);
void ufs_init_wlu(UfsLu *wlu, uint8_t wlun);
#endif /* HW_UFS_UFS_H */

View File

@ -379,7 +379,7 @@ typedef struct Attributes {
/* Command response result code */
typedef enum CommandRespCode {
UFS_COMMAND_RESULT_SUCESS = 0x00,
UFS_COMMAND_RESULT_SUCCESS = 0x00,
UFS_COMMAND_RESULT_FAIL = 0x01,
} CommandRespCode;

View File

@ -425,6 +425,9 @@ static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] = {
TEST_UNIT_READY,
};
const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
REQUEST_SENSE,
};
UtpTransferReqDesc utrd;
UtpUpiuRsp rsp_upiu;
@ -440,6 +443,12 @@ static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
/* There is one logical unit whose lun is 0 */
g_assert_cmpuint(buf[9], ==, 0);
/* Clear Unit Attention */
ufs_send_scsi_command(ufs, 0, 0, request_sense_cdb, NULL, 0, buf,
sizeof(buf), &utrd, &rsp_upiu);
g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
/* Check TEST_UNIT_READY */
ufs_send_scsi_command(ufs, 0, 0, test_unit_ready_cdb, NULL, 0, NULL, 0,
&utrd, &rsp_upiu);
@ -473,6 +482,9 @@ static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
0x00,
0x00
};
const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
REQUEST_SENSE,
};
const uint8_t read_cdb[UFS_CDB_SIZE] = {
/* READ(10) to LBA 0, transfer length 1 */
READ_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
@ -484,32 +496,39 @@ static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
uint32_t block_size;
UtpTransferReqDesc utrd;
UtpUpiuRsp rsp_upiu;
const int test_lun = 1;
ufs_init(ufs, alloc);
/* Clear Unit Attention */
ufs_send_scsi_command(ufs, 0, test_lun, request_sense_cdb, NULL, 0,
read_buf, sizeof(read_buf), &utrd, &rsp_upiu);
g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
/* Read capacity */
ufs_send_scsi_command(ufs, 0, 1, read_capacity_cdb, NULL, 0, read_buf,
sizeof(read_buf), &utrd, &rsp_upiu);
ufs_send_scsi_command(ufs, 0, test_lun, read_capacity_cdb, NULL, 0,
read_buf, sizeof(read_buf), &utrd, &rsp_upiu);
g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
UFS_COMMAND_RESULT_SUCESS);
UFS_COMMAND_RESULT_SUCCESS);
block_size = ldl_be_p(&read_buf[8]);
g_assert_cmpuint(block_size, ==, 4096);
/* Write data */
memset(write_buf, 0xab, block_size);
ufs_send_scsi_command(ufs, 0, 1, write_cdb, write_buf, block_size, NULL, 0,
&utrd, &rsp_upiu);
ufs_send_scsi_command(ufs, 0, test_lun, write_cdb, write_buf, block_size,
NULL, 0, &utrd, &rsp_upiu);
g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
UFS_COMMAND_RESULT_SUCESS);
UFS_COMMAND_RESULT_SUCCESS);
/* Read data and verify */
ufs_send_scsi_command(ufs, 0, 1, read_cdb, NULL, 0, read_buf, block_size,
&utrd, &rsp_upiu);
ufs_send_scsi_command(ufs, 0, test_lun, read_cdb, NULL, 0, read_buf,
block_size, &utrd, &rsp_upiu);
g_assert_cmpuint(le32_to_cpu(utrd.header.dword_2), ==, UFS_OCS_SUCCESS);
g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
UFS_COMMAND_RESULT_SUCESS);
UFS_COMMAND_RESULT_SUCCESS);
g_assert_cmpint(memcmp(read_buf, write_buf, block_size), ==, 0);
ufs_exit(ufs, alloc);