@@ -136,8 +136,10 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
trace_esp_do_busid_cmd(busid);
lun = busid & 7;
- current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
- s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
+ current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id,
+ scsi_lun_from_int(lun));
+ s->current_req = scsi_req_new(current_lun, 0, scsi_lun_from_int(lun),
+ buf, s);
datalen = scsi_req_enqueue(s->current_req);
s->ti_size = datalen;
if (datalen != 0) {
@@ -811,7 +811,7 @@ static void lsi_do_command(LSIState *s)
s->command_complete = 0;
id = (s->select_tag >> 8) & 0xf;
- dev = scsi_device_find(&s->bus, 0, id, s->current_lun);
+ dev = scsi_device_find(&s->bus, 0, id, scsi_lun_from_int(s->current_lun));
if (!dev) {
lsi_bad_selection(s, id);
return;
@@ -820,8 +820,9 @@ static void lsi_do_command(LSIState *s)
assert(s->current == NULL);
s->current = g_new0(lsi_request, 1);
s->current->tag = s->select_tag;
- s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun, buf,
- s->current);
+ s->current->req = scsi_req_new(dev, s->current->tag,
+ scsi_lun_from_int(s->current_lun),
+ buf, s->current);
n = scsi_req_enqueue(s->current->req);
if (n) {
@@ -756,7 +756,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
uint16_t pd_id;
if (num_pd_disks < 8) {
- pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
+ pd_id = ((sdev->id & 0xFF) << 8) | scsi_lun_to_int(sdev->lun);
info.device.port_addr[num_pd_disks] =
cpu_to_le64(megasas_get_sata_addr(pd_id));
}
@@ -975,7 +975,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
if (num_pd_disks >= max_pd_disks)
break;
- pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
+ pd_id = ((sdev->id & 0xFF) << 8) | scsi_lun_to_int(sdev->lun);
info.addr[num_pd_disks].device_id = cpu_to_le16(pd_id);
info.addr[num_pd_disks].encl_device_id = 0xFFFF;
info.addr[num_pd_disks].encl_index = 0;
@@ -1028,7 +1028,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */
info->vpd_page83[0] = 0x7f;
megasas_setup_inquiry(cmdbuf, 0, sizeof(info->inquiry_data));
- cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
+ cmd->req = scsi_req_new(sdev, cmd->index, scsi_lun_from_int(lun),
+ cmdbuf, cmd);
if (!cmd->req) {
trace_megasas_dcmd_req_alloc_failed(cmd->index,
"PD get info std inquiry");
@@ -1110,7 +1111,7 @@ static int megasas_dcmd_pd_get_info(MegasasState *s, MegasasCmd *cmd)
pd_id = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
target_id = (pd_id >> 8) & 0xFF;
lun_id = pd_id & 0xFF;
- sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
+ sdev = scsi_device_find(&s->bus, 0, target_id, scsi_lun_from_int(lun_id));
trace_megasas_dcmd_pd_get_info(cmd->index, pd_id);
if (sdev) {
@@ -1200,7 +1201,7 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
if (num_ld_disks >= max_ld_disks) {
break;
}
- info.targetid[num_ld_disks] = sdev->lun;
+ info.targetid[num_ld_disks] = scsi_lun_to_int(sdev->lun);
num_ld_disks++;
dcmd_size++;
}
@@ -1335,7 +1336,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
SCSIDevice *sdev = SCSI_DEVICE(kid->child);
- uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
+ uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | scsi_lun_to_int(sdev->lun);
struct mfi_array *array;
struct mfi_ld_config *ld;
uint64_t pd_size;
@@ -1595,7 +1596,7 @@ static int megasas_finish_internal_dcmd(MegasasCmd *cmd,
SCSIRequest *req, size_t resid)
{
int retval = MFI_STAT_OK;
- int lun = req->lun;
+ int lun = scsi_lun_to_int(req->lun);
trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun);
cmd->iov_size -= resid;
@@ -1671,7 +1672,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
return MFI_STAT_DEVICE_NOT_FOUND;
}
}
- sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
+ sdev = scsi_device_find(&s->bus, 0, target_id, scsi_lun_from_int(lun_id));
cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len);
trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical,
@@ -1700,7 +1701,8 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
return MFI_STAT_SCSI_DONE_WITH_ERROR;
}
- cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd);
+ cmd->req = scsi_req_new(sdev, cmd->index, scsi_lun_from_int(lun_id),
+ cdb, cmd);
if (!cmd->req) {
trace_megasas_scsi_req_alloc_failed(
mfi_frame_desc[frame_cmd], target_id, lun_id);
@@ -1744,7 +1746,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
cdb_len = cmd->frame->header.cdb_len;
if (target_id < MFI_MAX_LD && lun_id == 0) {
- sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
+ sdev = scsi_device_find(&s->bus, 0, target_id, 0);
}
trace_megasas_handle_io(cmd->index,
@@ -1775,7 +1777,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
megasas_encode_lba(cdb, lba_start, lba_count, is_write);
cmd->req = scsi_req_new(sdev, cmd->index,
- lun_id, cdb, cmd);
+ scsi_lun_from_int(lun_id), cdb, cmd);
if (!cmd->req) {
trace_megasas_scsi_req_alloc_failed(
mfi_frame_desc[frame_cmd], target_id, lun_id);
@@ -276,7 +276,7 @@ static int mptsas_scsi_device_find(MPTSASState *s, int bus, int target,
return MPI_IOCSTATUS_SCSI_INVALID_TARGETID;
}
- *sdev = scsi_device_find(&s->bus, bus, target, lun[1]);
+ *sdev = scsi_device_find(&s->bus, bus, target, scsi_lun_from_str(lun));
if (!*sdev) {
return MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE;
}
@@ -322,7 +322,7 @@ static int mptsas_process_scsi_io_request(MPTSASState *s,
}
req->sreq = scsi_req_new(sdev, scsi_io->MsgContext,
- scsi_io->LUN[1], scsi_io->CDB, req);
+ sdev->lun, scsi_io->CDB, req);
if (req->sreq->cmd.xfer > scsi_io->DataLength) {
goto overrun;
@@ -430,7 +430,7 @@ static void mptsas_process_scsi_task_mgmt(MPTSASState *s, MPIMsgSCSITaskMgmt *re
reply.IOCStatus = status;
goto out;
}
- if (sdev->lun != req->LUN[1]) {
+ if (sdev->lun != scsi_lun_from_str(req->LUN)) {
reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;
goto out;
}
@@ -477,7 +477,7 @@ static void mptsas_process_scsi_task_mgmt(MPTSASState *s, MPIMsgSCSITaskMgmt *re
reply.IOCStatus = status;
goto out;
}
- if (sdev->lun != req->LUN[1]) {
+ if (sdev->lun != scsi_lun_from_str(req->LUN)) {
reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;
goto out;
}
@@ -515,7 +515,7 @@ reply_maybe_async:
reply.IOCStatus = status;
goto out;
}
- if (sdev->lun != req->LUN[1]) {
+ if (sdev->lun != scsi_lun_from_str(req->LUN)) {
reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;
goto out;
}
@@ -20,7 +20,7 @@ static void scsi_target_free_buf(SCSIRequest *req);
static Property scsi_props[] = {
DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
- DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
+ DEFINE_PROP_UINT64("lun", SCSIDevice, lun, -1),
DEFINE_PROP_END_OF_LIST(),
};
@@ -68,7 +68,7 @@ int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
return rc;
}
-static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t lun,
+static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint64_t lun,
uint8_t *buf, void *hba_private)
{
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
@@ -147,6 +147,22 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
}
}
+static int scsi_device_count(SCSIBus *bus, int channel, int id)
+{
+ BusChild *kid;
+ int luns = 0;
+
+ QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) {
+ DeviceState *qdev = kid->child;
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
+
+ if (dev->channel == channel && dev->id == id) {
+ luns++;
+ }
+ }
+ return luns;
+}
+
static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
{
SCSIDevice *dev = SCSI_DEVICE(qdev);
@@ -162,9 +178,15 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
error_setg(errp, "bad scsi device id: %d", dev->id);
return;
}
- if (dev->lun != -1 && dev->lun > bus->info->max_lun) {
- error_setg(errp, "bad scsi device lun: %d", dev->lun);
- return;
+ if (dev->lun != -1) {
+ /* Compat: commandline might have passed old-style linear LUN */
+ if (dev->lun < 0xffff) {
+ if (dev->lun > bus->info->max_lun) {
+ error_setg(errp, "bad scsi device lun: %"PRIu64"", dev->lun);
+ return;
+ }
+ dev->lun = scsi_lun_from_int(dev->lun);
+ }
}
if (dev->id == -1) {
@@ -181,15 +203,18 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
}
dev->id = id;
} else if (dev->lun == -1) {
- int lun = -1;
+ int lun = 0;
do {
- d = scsi_device_find(bus, dev->channel, dev->id, ++lun);
- } while (d && d->lun == lun && lun < bus->info->max_lun);
- if (d && d->lun == lun) {
+ d = scsi_device_find(bus, dev->channel, dev->id,
+ scsi_lun_from_int(lun));
+ lun++;
+ } while (d && scsi_lun_to_int(d->lun) == lun &&
+ lun < bus->info->max_lun);
+ if (d && scsi_lun_to_int(d->lun) == lun) {
error_setg(errp, "no free lun");
return;
}
- dev->lun = lun;
+ dev->lun = scsi_lun_from_int(lun);
} else {
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
assert(d);
@@ -197,6 +222,10 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
error_setg(errp, "lun already used by '%s'", d->qdev.id);
return;
}
+ if (scsi_device_count(bus, dev->channel, dev->id) >= bus->info->max_lun) {
+ error_setg(errp, "bad scsi device lun: %"PRIu64"", dev->lun);
+ return;
+ }
}
QTAILQ_INIT(&dev->requests);
@@ -385,16 +414,6 @@ struct SCSITargetReq {
int buf_len;
};
-static void store_lun(uint8_t *outbuf, int lun)
-{
- if (lun < 256) {
- outbuf[1] = lun;
- return;
- }
- outbuf[1] = (lun & 255);
- outbuf[0] = (lun >> 8) | 0x40;
-}
-
static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
{
BusChild *kid;
@@ -438,7 +457,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
- store_lun(&r->buf[i], dev->lun);
+ scsi_lun_to_str(dev->lun, &r->buf[i]);
i += 8;
}
}
@@ -631,7 +650,7 @@ static const struct SCSIReqOps reqops_target_command = {
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
- uint32_t tag, uint32_t lun, void *hba_private)
+ uint32_t tag, uint64_t lun, void *hba_private)
{
SCSIRequest *req;
SCSIBus *bus = scsi_bus_from_device(d);
@@ -652,11 +671,11 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
object_ref(OBJECT(d));
object_ref(OBJECT(qbus->parent));
notifier_list_init(&req->cancel_notifiers);
- trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
+ trace_scsi_req_alloc(req->dev->id, scsi_lun_to_int(req->lun), req->tag);
return req;
}
-SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
+SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint64_t lun,
uint8_t *buf, void *hba_private)
{
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
@@ -694,14 +713,14 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
}
if (ret != 0) {
- trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
+ trace_scsi_req_parse_bad(d->id, scsi_lun_to_int(lun), tag, buf[0]);
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
} else {
assert(cmd.len != 0);
- trace_scsi_req_parsed(d->id, lun, tag, buf[0],
+ trace_scsi_req_parsed(d->id, scsi_lun_to_int(lun), tag, buf[0],
cmd.mode, cmd.xfer);
if (cmd.lba != -1) {
- trace_scsi_req_parsed_lba(d->id, lun, tag, buf[0],
+ trace_scsi_req_parsed_lba(d->id, scsi_lun_to_int(lun), tag, buf[0],
cmd.lba);
}
@@ -719,16 +738,17 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
switch (buf[0]) {
case INQUIRY:
- trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]);
+ trace_scsi_inquiry(d->id, scsi_lun_to_int(lun), tag,
+ cmd.buf[1], cmd.buf[2]);
break;
case TEST_UNIT_READY:
- trace_scsi_test_unit_ready(d->id, lun, tag);
+ trace_scsi_test_unit_ready(d->id, scsi_lun_to_int(lun), tag);
break;
case REPORT_LUNS:
- trace_scsi_report_luns(d->id, lun, tag);
+ trace_scsi_report_luns(d->id, scsi_lun_to_int(lun), tag);
break;
case REQUEST_SENSE:
- trace_scsi_request_sense(d->id, lun, tag);
+ trace_scsi_request_sense(d->id, scsi_lun_to_int(lun), tag);
break;
default:
break;
@@ -816,8 +836,8 @@ int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed)
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
{
- trace_scsi_req_build_sense(req->dev->id, req->lun, req->tag,
- sense.key, sense.asc, sense.ascq);
+ trace_scsi_req_build_sense(req->dev->id, scsi_lun_to_int(req->lun),
+ req->tag, sense.key, sense.asc, sense.ascq);
req->sense_len = scsi_build_sense(req->sense, sense);
}
@@ -848,7 +868,7 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
static void scsi_req_dequeue(SCSIRequest *req)
{
- trace_scsi_req_dequeue(req->dev->id, req->lun, req->tag);
+ trace_scsi_req_dequeue(req->dev->id, scsi_lun_to_int(req->lun), req->tag);
req->retry = false;
if (req->enqueued) {
QTAILQ_REMOVE(&req->dev->requests, req, next);
@@ -1339,10 +1359,11 @@ void scsi_req_unref(SCSIRequest *req)
void scsi_req_continue(SCSIRequest *req)
{
if (req->io_canceled) {
- trace_scsi_req_continue_canceled(req->dev->id, req->lun, req->tag);
+ trace_scsi_req_continue_canceled(req->dev->id,
+ scsi_lun_to_int(req->lun), req->tag);
return;
}
- trace_scsi_req_continue(req->dev->id, req->lun, req->tag);
+ trace_scsi_req_continue(req->dev->id, scsi_lun_to_int(req->lun), req->tag);
if (req->cmd.mode == SCSI_XFER_TO_DEV) {
req->ops->write_data(req);
} else {
@@ -1357,10 +1378,11 @@ void scsi_req_data(SCSIRequest *req, int len)
{
uint8_t *buf;
if (req->io_canceled) {
- trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
+ trace_scsi_req_data_canceled(req->dev->id, scsi_lun_to_int(req->lun),
+ req->tag, len);
return;
}
- trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
+ trace_scsi_req_data(req->dev->id, scsi_lun_to_int(req->lun), req->tag, len);
assert(req->cmd.mode != SCSI_XFER_NONE);
if (!req->sg) {
req->resid -= len;
@@ -1463,7 +1485,7 @@ void scsi_req_cancel_complete(SCSIRequest *req)
* */
void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier)
{
- trace_scsi_req_cancel(req->dev->id, req->lun, req->tag);
+ trace_scsi_req_cancel(req->dev->id, scsi_lun_to_int(req->lun), req->tag);
if (notifier) {
notifier_list_add(&req->cancel_notifiers, notifier);
}
@@ -1488,7 +1510,7 @@ void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier)
void scsi_req_cancel(SCSIRequest *req)
{
- trace_scsi_req_cancel(req->dev->id, req->lun, req->tag);
+ trace_scsi_req_cancel(req->dev->id, scsi_lun_to_int(req->lun), req->tag);
if (!req->enqueued) {
return;
}
@@ -1539,7 +1561,7 @@ void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense)
if (sense.key != UNIT_ATTENTION) {
return;
}
- trace_scsi_device_set_ua(sdev->id, sdev->lun, sense.key,
+ trace_scsi_device_set_ua(sdev->id, scsi_lun_to_int(sdev->lun), sense.key,
sense.asc, sense.ascq);
/*
@@ -1576,9 +1598,21 @@ static char *scsibus_get_dev_path(DeviceState *dev)
id = qdev_get_dev_path(hba);
if (id) {
- path = g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun);
+ if (scsi_lun_to_int(d->lun) < 0x3fff) {
+ path = g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id,
+ scsi_lun_to_int(d->lun));
+ } else {
+ path = g_strdup_printf("%s/%d:%d:%"PRIx64"", id, d->channel, d->id,
+ d->lun);
+ }
} else {
- path = g_strdup_printf("%d:%d:%d", d->channel, d->id, d->lun);
+ if (scsi_lun_to_int(d->lun) < 0x3fff) {
+ path = g_strdup_printf("%d:%d:%d", d->channel, d->id,
+ scsi_lun_to_int(d->lun));
+ } else {
+ path = g_strdup_printf("%d:%d:%"PRIu64"", d->channel, d->id,
+ d->lun);
+ }
}
g_free(id);
return path;
@@ -1587,11 +1621,16 @@ static char *scsibus_get_dev_path(DeviceState *dev)
static char *scsibus_get_fw_dev_path(DeviceState *dev)
{
SCSIDevice *d = SCSI_DEVICE(dev);
- return g_strdup_printf("channel@%x/%s@%x,%x", d->channel,
- qdev_fw_name(dev), d->id, d->lun);
+ if (scsi_lun_to_int(d->lun) > 0x3fff) {
+ return g_strdup_printf("channel@%x/%s@%x,%d", d->channel,
+ qdev_fw_name(dev), d->id, scsi_lun_to_int(d->lun));
+ } else {
+ return g_strdup_printf("channel@%x/%s@%x,%"PRIx64"", d->channel,
+ qdev_fw_name(dev), d->id, d->lun);
+ }
}
-SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, uint64_t lun)
{
BusChild *kid;
SCSIDevice *target_dev = NULL;
@@ -1618,6 +1657,7 @@ static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
SCSIRequest *req;
+ uint32_t lun;
QTAILQ_FOREACH(req, &s->requests, next) {
assert(!req->io_canceled);
@@ -1626,8 +1666,9 @@ static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
qemu_put_sbyte(f, req->retry ? 1 : 2);
qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
+ lun = (uint32_t)((req->lun >> 32) & 0xFFFFFFFF);
qemu_put_be32s(f, &req->tag);
- qemu_put_be32s(f, &req->lun);
+ qemu_put_be32s(f, &lun);
if (bus->info->save_request) {
bus->info->save_request(f, req);
}
@@ -1656,7 +1697,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size,
qemu_get_buffer(f, buf, sizeof(buf));
qemu_get_be32s(f, &tag);
qemu_get_be32s(f, &lun);
- req = scsi_req_new(s, tag, lun, buf, NULL);
+ req = scsi_req_new(s, tag, (uint64_t)lun << 32, buf, NULL);
req->retry = (sbyte == 1);
if (bus->info->load_request) {
req->hba_private = bus->info->load_request(f, req);
@@ -2517,7 +2517,7 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
[WRITE_VERIFY_16] = &scsi_disk_dma_reqops,
};
-static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
+static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint64_t lun,
uint8_t *buf, void *hba_private)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
@@ -2533,7 +2533,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
req = scsi_req_alloc(ops, &s->qdev, tag, lun, hba_private);
#ifdef DEBUG_SCSI
- DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
+ DPRINTF("Command: lun=%"PRIu64" tag=0x%x data=0x%02x", lun, tag, buf[0]);
{
int i;
for (i = 1; i < scsi_cdb_length(buf); i++) {
@@ -2847,7 +2847,7 @@ static const SCSIReqOps scsi_block_dma_reqops = {
};
static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
- uint32_t lun, uint8_t *buf,
+ uint64_t lun, uint8_t *buf,
void *hba_private)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
@@ -557,7 +557,7 @@ const SCSIReqOps scsi_generic_req_ops = {
.save_request = scsi_generic_save_request,
};
-static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
+static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint64_t lun,
uint8_t *buf, void *hba_private)
{
return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
@@ -136,9 +136,9 @@ static void vscsi_put_req(vscsi_req *req)
req->active = 0;
}
-static SCSIDevice *vscsi_device_find(SCSIBus *bus, uint64_t srp_lun, int *lun)
+static SCSIDevice *vscsi_device_find(SCSIBus *bus, uint64_t srp_lun, uint64_t *lun)
{
- int channel = 0, id = 0;
+ int channel = 0, id = 0, l;
retry:
switch (srp_lun >> 62) {
@@ -149,16 +149,16 @@ retry:
srp_lun <<= 16;
goto retry;
}
- *lun = (srp_lun >> 48) & 0xff;
+ l = (srp_lun >> 48) & 0xff;
break;
case 1:
- *lun = (srp_lun >> 48) & 0x3fff;
+ l = (srp_lun >> 48) & 0x3fff;
break;
case 2:
channel = (srp_lun >> 53) & 0x7;
id = (srp_lun >> 56) & 0x3f;
- *lun = (srp_lun >> 48) & 0x1f;
+ l = (srp_lun >> 48) & 0x1f;
break;
case 3:
*lun = -1;
@@ -166,7 +166,7 @@ retry:
default:
abort();
}
-
+ *lun = scsi_lun_from_int(l);
return scsi_device_find(bus, channel, id, *lun);
}
@@ -752,7 +752,7 @@ static void vscsi_report_luns(VSCSIState *s, vscsi_req *req)
}
resp_data[i] |= dev->id;
resp_data[i+1] = (dev->channel << 5);
- resp_data[i+1] |= dev->lun;
+ resp_data[i+1] |= scsi_lun_to_int(dev->lun);
i += 8;
}
@@ -822,8 +822,9 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
{
union viosrp_iu *iu = &req->iu;
vscsi_req *tmpreq;
- int i, lun = 0, resp = SRP_TSK_MGMT_COMPLETE;
+ int i, resp = SRP_TSK_MGMT_COMPLETE;
SCSIDevice *d;
+ uint64_t lun = 0;
uint64_t tag = iu->srp.rsp.tag;
uint8_t sol_not = iu->srp.cmd.sol_not;
@@ -25,9 +25,9 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
-static inline int virtio_scsi_get_lun(uint8_t *lun)
+static inline uint64_t virtio_scsi_get_lun(uint8_t *lun)
{
- return ((lun[2] << 8) | lun[3]) & 0x3FFF;
+ return (((uint64_t)(lun[2] << 8) | lun[3]) & 0x3FFF) << 48;
}
static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
@@ -737,10 +737,10 @@ void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
evt->lun[1] = dev->id;
/* Linux wants us to keep the same encoding we use for REPORT LUNS. */
- if (dev->lun >= 256) {
- evt->lun[2] = (dev->lun >> 8) | 0x40;
+ if (scsi_lun_to_int(dev->lun) >= 256) {
+ evt->lun[2] = (scsi_lun_to_int(dev->lun) >> 8) | 0x40;
}
- evt->lun[3] = dev->lun & 0xFF;
+ evt->lun[3] = scsi_lun_to_int(dev->lun) & 0xFF;
}
virtio_scsi_complete_req(req);
}
@@ -135,7 +135,7 @@ typedef struct PVSCSIRequest {
PVSCSIState *dev;
uint8_t sense_key;
uint8_t completed;
- int lun;
+ uint64_t lun;
QEMUSGList sgl;
PVSCSISGState sg;
struct PVSCSIRingReqDesc req;
@@ -551,7 +551,7 @@ pvscsi_send_msg(PVSCSIState *s, SCSIDevice *dev, uint32_t msg_type)
msg.type = msg_type;
msg.bus = dev->channel;
msg.target = dev->id;
- msg.lun[1] = dev->lun;
+ scsi_lun_to_str(dev->lun, msg.lun);
pvscsi_msg_ring_put(s, (PVSCSIRingMsgDesc *)&msg);
pvscsi_ring_flush_msg(&s->rings);
@@ -597,15 +597,15 @@ pvscsi_request_cancelled(SCSIRequest *req)
static SCSIDevice*
pvscsi_device_find(PVSCSIState *s, int channel, int target,
- uint8_t *requested_lun, uint8_t *target_lun)
+ uint8_t *requested_lun, uint64_t *target_lun)
{
- if (requested_lun[0] || requested_lun[2] || requested_lun[3] ||
- requested_lun[4] || requested_lun[5] || requested_lun[6] ||
- requested_lun[7] || (target > PVSCSI_MAX_DEVS)) {
+ uint64_t lun64 = scsi_lun_from_str(requested_lun);
+
+ if (scsi_lun_to_int(lun64) > 255 || (target > PVSCSI_MAX_DEVS)) {
return NULL;
} else {
- *target_lun = requested_lun[1];
- return scsi_device_find(&s->bus, channel, target, *target_lun);
+ *target_lun = lun64;
+ return scsi_device_find(&s->bus, channel, target, lun64);
}
}
@@ -614,7 +614,7 @@ pvscsi_queue_pending_descriptor(PVSCSIState *s, SCSIDevice **d,
struct PVSCSIRingReqDesc *descr)
{
PVSCSIRequest *pvscsi_req;
- uint8_t lun;
+ uint64_t lun;
pvscsi_req = g_malloc0(sizeof(*pvscsi_req));
pvscsi_req->dev = s;
@@ -823,14 +823,14 @@ pvscsi_on_cmd_unknown(PVSCSIState *s)
static uint64_t
pvscsi_on_cmd_reset_device(PVSCSIState *s)
{
- uint8_t target_lun = 0;
+ uint64_t target_lun = 0;
struct PVSCSICmdDescResetDevice *cmd =
(struct PVSCSICmdDescResetDevice *) s->curr_cmd_data;
SCSIDevice *sdev;
sdev = pvscsi_device_find(s, 0, cmd->target, cmd->lun, &target_lun);
- trace_pvscsi_on_cmd_reset_dev(cmd->target, (int) target_lun, sdev);
+ trace_pvscsi_on_cmd_reset_dev(cmd->target, scsi_lun_to_int(target_lun), sdev);
if (sdev != NULL) {
s->resetting++;
@@ -371,11 +371,12 @@ static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
case ClassInterfaceRequest | GetMaxLun:
maxlun = 0;
for (;;) {
- scsi_dev = scsi_device_find(&s->bus, 0, 0, maxlun+1);
+ scsi_dev = scsi_device_find(&s->bus, 0, 0,
+ scsi_lun_from_int(maxlun+1));
if (scsi_dev == NULL) {
break;
}
- if (scsi_dev->lun != maxlun+1) {
+ if (scsi_lun_to_int(scsi_dev->lun) != maxlun+1) {
break;
}
maxlun++;
@@ -429,7 +430,8 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
goto fail;
}
DPRINTF("Command on LUN %d\n", cbw.lun);
- scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun);
+ scsi_dev = scsi_device_find(&s->bus, 0, 0,
+ scsi_lun_from_int(cbw.lun));
if (scsi_dev == NULL) {
error_report("usb-msd: Bad LUN %d", cbw.lun);
goto fail;
@@ -447,7 +449,8 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
tag, cbw.flags, cbw.cmd_len, s->data_len);
assert(le32_to_cpu(s->csw.residue) == 0);
s->scsi_len = 0;
- s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL);
+ s->req = scsi_req_new(scsi_dev, tag, scsi_lun_from_int(cbw.lun),
+ cbw.cmd, NULL);
#ifdef DEBUG_MSD
scsi_req_print(s->req);
#endif
@@ -461,19 +461,6 @@ static void usb_uas_queue_write_ready(UASRequest *req)
/* --------------------------------------------------------------------- */
-static int usb_uas_get_lun(uint64_t lun64)
-{
- return (lun64 >> 48) & 0xff;
-}
-
-static SCSIDevice *usb_uas_get_dev(UASDevice *uas, uint64_t lun64)
-{
- if ((lun64 >> 56) != 0x00) {
- return NULL;
- }
- return scsi_device_find(&uas->bus, 0, 0, usb_uas_get_lun(lun64));
-}
-
static void usb_uas_complete_data_packet(UASRequest *req)
{
USBPacket *p;
@@ -547,7 +534,7 @@ static UASRequest *usb_uas_alloc_request(UASDevice *uas, uas_iu *iu)
req->uas = uas;
req->tag = be16_to_cpu(iu->hdr.tag);
req->lun = be64_to_cpu(iu->command.lun);
- req->dev = usb_uas_get_dev(req->uas, req->lun);
+ req->dev = scsi_device_find(&uas->bus, 0, 0, req->lun);
return req;
}
@@ -709,7 +696,7 @@ static void usb_uas_command(UASDevice *uas, uas_iu *iu)
}
trace_usb_uas_command(uas->dev.addr, req->tag,
- usb_uas_get_lun(req->lun),
+ scsi_lun_to_int(req->lun),
req->lun >> 32, req->lun & 0xffffffff);
QTAILQ_INSERT_TAIL(&uas->requests, req, next);
if (uas_using_streams(uas) && uas->data3[req->tag] != NULL) {
@@ -719,7 +706,7 @@ static void usb_uas_command(UASDevice *uas, uas_iu *iu)
}
req->req = scsi_req_new(req->dev, req->tag,
- usb_uas_get_lun(req->lun),
+ scsi_lun_to_int(req->lun),
iu->command.cdb, req);
if (uas->requestlog) {
scsi_req_print(req->req);
@@ -747,9 +734,8 @@ bad_target:
static void usb_uas_task(UASDevice *uas, uas_iu *iu)
{
uint16_t tag = be16_to_cpu(iu->hdr.tag);
- uint64_t lun64 = be64_to_cpu(iu->task.lun);
- SCSIDevice *dev = usb_uas_get_dev(uas, lun64);
- int lun = usb_uas_get_lun(lun64);
+ uint64_t lun = be64_to_cpu(iu->task.lun);
+ SCSIDevice *dev = scsi_device_find(&uas->bus, 0, 0, lun);
UASRequest *req;
uint16_t task_tag;
@@ -776,7 +762,8 @@ static void usb_uas_task(UASDevice *uas, uas_iu *iu)
break;
case UAS_TMF_LOGICAL_UNIT_RESET:
- trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag, lun);
+ trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag,
+ scsi_lun_to_int(lun));
qdev_reset_all(&dev->qdev);
usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE);
break;
@@ -23,9 +23,9 @@ struct SCSIRequest {
SCSIDevice *dev;
const SCSIReqOps *ops;
uint32_t refcount;
- uint32_t tag;
- uint32_t lun;
uint32_t status;
+ uint32_t tag;
+ uint64_t lun;
void *hba_private;
size_t resid;
SCSICommand cmd;
@@ -61,7 +61,7 @@ typedef struct SCSIDeviceClass {
void (*realize)(SCSIDevice *dev, Error **errp);
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
void *hba_private);
- SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
+ SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint64_t lun,
uint8_t *buf, void *hba_private);
void (*unit_attention_reported)(SCSIDevice *s);
} SCSIDeviceClass;
@@ -79,7 +79,7 @@ struct SCSIDevice
uint32_t sense_len;
QTAILQ_HEAD(, SCSIRequest) requests;
uint32_t channel;
- uint32_t lun;
+ uint64_t lun;
int blocksize;
int type;
uint64_t max_lba;
@@ -149,6 +149,48 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
}
+static inline uint64_t scsi_lun_from_int(unsigned int lun)
+{
+ if (lun < 256) {
+ /* Use peripheral addressing */
+ return (uint64_t)lun << 48;
+ } else if (lun < 0x3fff) {
+ /* Use flat space addressing */
+ return ((uint64_t)lun | 0x4000) << 48;
+ }
+ /* Return Logical unit not specified addressing */
+ return (uint64_t)-1;
+}
+
+static inline int scsi_lun_to_int(uint64_t lun64)
+{
+ return (lun64 >> 48) & 0x3fff;
+}
+
+static inline uint64_t scsi_lun_from_str(uint8_t *lun)
+{
+ int i;
+ uint64_t lun64 = 0;
+
+ for (i = 0; i < 8; i += 2) {
+ lun64 |= (uint64_t)lun[i] << ((i + 1) * 8) |
+ (uint64_t)lun[i + 1] << (i * 8);
+ }
+ return lun64;
+}
+
+static inline void scsi_lun_to_str(uint64_t lun64, uint8_t *lun)
+{
+ int i;
+
+ memset(lun, 0, 8);
+ for (i = 6; i >= 0; i -= 2) {
+ lun[i] = (lun64 >> 8) & 0xFF;
+ lun[i + 1] = lun64 & 0xFF;
+ lun64 = lun64 >> 16;
+ }
+}
+
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
int unit, bool removable, int bootindex,
const char *serial, Error **errp);
@@ -156,8 +198,8 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated);
void scsi_legacy_handle_cmdline(void);
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
- uint32_t tag, uint32_t lun, void *hba_private);
-SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
+ uint32_t tag, uint64_t lun, void *hba_private);
+SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint64_t lun,
uint8_t *buf, void *hba_private);
int32_t scsi_req_enqueue(SCSIRequest *req);
SCSIRequest *scsi_req_ref(SCSIRequest *req);
@@ -183,7 +225,7 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
void scsi_device_unit_attention_reported(SCSIDevice *dev);
void scsi_generic_read_device_identification(SCSIDevice *dev);
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
-SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, uint64_t lun);
/* scsi-generic.c. */
extern const SCSIReqOps scsi_generic_req_ops;
The LUN value really is a 64-bit number, so we should as well treat it as such. And we should be using accessor functions to provide backwards compability. Signed-off-by: Hannes Reinecke <hare@suse.com> --- hw/scsi/esp.c | 6 ++- hw/scsi/lsi53c895a.c | 7 +-- hw/scsi/megasas.c | 24 +++++---- hw/scsi/mptsas.c | 10 ++-- hw/scsi/scsi-bus.c | 137 ++++++++++++++++++++++++++++++++----------------- hw/scsi/scsi-disk.c | 6 +-- hw/scsi/scsi-generic.c | 2 +- hw/scsi/spapr_vscsi.c | 17 +++--- hw/scsi/virtio-scsi.c | 10 ++-- hw/scsi/vmw_pvscsi.c | 22 ++++---- hw/usb/dev-storage.c | 11 ++-- hw/usb/dev-uas.c | 27 +++------- include/hw/scsi/scsi.h | 56 +++++++++++++++++--- 13 files changed, 207 insertions(+), 128 deletions(-)