[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 07/28] scsi-generic: grab device and port SAS address
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 07/28] scsi-generic: grab device and port SAS addresses from backend |
Date: |
Mon, 8 Feb 2016 18:02:58 +0100 |
This lets a SAS adapter expose them through its own configuration
mechanism.
Signed-off-by: Paolo Bonzini <address@hidden>
---
hw/scsi/scsi-disk.c | 1 +
hw/scsi/scsi-generic.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/scsi/scsi.h | 1 +
3 files changed, 94 insertions(+)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index fd12fbb..469aec2 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2573,6 +2573,7 @@ static void scsi_block_realize(SCSIDevice *dev, Error
**errp)
s->features |= (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS);
scsi_realize(&s->qdev, errp);
+ scsi_generic_read_device_identification(&s->qdev);
}
static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 75a4127..f8a1ff2 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -355,6 +355,96 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t
*cmd)
}
}
+static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
+{
+ int i;
+
+ if ((p[1] & 0xF) == 3) {
+ /* NAA designator type */
+ if (p[3] != 8) {
+ return -EINVAL;
+ }
+ *p_wwn = ldq_be_p(p + 4);
+ return 0;
+ }
+
+ if ((p[1] & 0xF) == 8) {
+ /* SCSI name string designator type */
+ if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
+ return -EINVAL;
+ }
+ if (p[3] > 20 && p[24] != ',') {
+ return -EINVAL;
+ }
+ *p_wwn = 0;
+ for (i = 8; i < 24; i++) {
+ char c = toupper(p[i]);
+ c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
+ *p_wwn = (*p_wwn << 4) | c;
+ }
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+void scsi_generic_read_device_identification(SCSIDevice *s)
+{
+ uint8_t cmd[6];
+ uint8_t buf[250];
+ uint8_t sensebuf[8];
+ sg_io_hdr_t io_header;
+ int ret;
+ int i, len;
+
+ memset(cmd, 0, sizeof(cmd));
+ memset(buf, 0, sizeof(buf));
+ cmd[0] = INQUIRY;
+ cmd[1] = 1;
+ cmd[2] = 0x83;
+ cmd[4] = sizeof(buf);
+
+ memset(&io_header, 0, sizeof(io_header));
+ io_header.interface_id = 'S';
+ io_header.dxfer_direction = SG_DXFER_FROM_DEV;
+ io_header.dxfer_len = sizeof(buf);
+ io_header.dxferp = buf;
+ io_header.cmdp = cmd;
+ io_header.cmd_len = sizeof(cmd);
+ io_header.mx_sb_len = sizeof(sensebuf);
+ io_header.sbp = sensebuf;
+ io_header.timeout = 6000; /* XXX */
+
+ ret = blk_ioctl(s->conf.blk, SG_IO, &io_header);
+ if (ret < 0 || io_header.driver_status || io_header.host_status) {
+ return;
+ }
+
+ len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
+ for (i = 0; i + 3 <= len; ) {
+ const uint8_t *p = &buf[i + 4];
+ uint64_t wwn;
+
+ if (i + (p[3] + 4) > len) {
+ break;
+ }
+
+ if ((p[1] & 0x10) == 0) {
+ /* Associated with the logical unit */
+ if (read_naa_id(p, &wwn) == 0) {
+ s->wwn = wwn;
+ }
+ } else if ((p[1] & 0x10) == 0x10) {
+ /* Associated with the target port */
+ if (read_naa_id(p, &wwn) == 0) {
+ s->port_wwn = wwn;
+ }
+ }
+
+ i += p[3] + 4;
+ }
+}
+
static int get_stream_blocksize(BlockBackend *blk)
{
uint8_t cmd[6];
@@ -458,6 +548,8 @@ static void scsi_generic_realize(SCSIDevice *s, Error
**errp)
}
DPRINTF("block size %d\n", s->blocksize);
+
+ scsi_generic_read_device_identification(s);
}
const SCSIReqOps scsi_generic_req_ops = {
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index bbabba2..29052f8 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -273,6 +273,7 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense
sense);
void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
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);
--
1.8.3.1
- [Qemu-devel] [PULL 00/28] Misc changes for 2016-02-08, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 01/28] memory: add early bail out from cpu_physical_memory_set_dirty_range, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 03/28] qemu-char: Keep pty slave file descriptor open until the master is closed, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 02/28] memory: RCU ram_list.dirty_memory[] for safe RAM hotplug, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 06/28] scsi: push WWN fields up to SCSIDevice, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 07/28] scsi-generic: grab device and port SAS addresses from backend,
Paolo Bonzini <=
- [Qemu-devel] [PULL 05/28] include/qemu/atomic.h: default to __atomic functions, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 04/28] configure: sanity check the glib library that pkg-config finds, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 09/28] qemu-nbd: Fix unintended texi verbatim formatting, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 12/28] scripts/kvm/kvm_stat: Fix tracefs access checking, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 14/28] kvm-all: trace: strerror fixup, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 17/28] target-i386: Introduce mo_stacksize, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 15/28] char: fix repeated registration of tcp chardev I/O handlers, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 18/28] target-i386: Use gen_lea_v_seg in gen_lea_modrm, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 19/28] target-i386: Use gen_lea_v_seg in stack subroutines, Paolo Bonzini, 2016/02/08
- [Qemu-devel] [PULL 10/28] qemu-nbd: Minor texi updates, Paolo Bonzini, 2016/02/08