aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi/spapr_vscsi.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-03-07 16:36:37 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-03-07 16:36:38 +0000
commitbb2b04503497608cdc5fa4c990d26e936f9d2102 (patch)
tree6e04a6aba5e21207af95f7a9390e506959b9d0e5 /hw/scsi/spapr_vscsi.c
parentc3f8d28e455bff9bde2b81bd0c9b1d437b88c159 (diff)
parent0f20ba62c35e6a779ba4ea00616192ef2abb6896 (diff)
Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-03-05 This pull request includes: - VSX emulation support - book3s pr/hv selection - some bug fixes - qdev stable numbering - eTSEC emulation # gpg: Signature made Wed 05 Mar 2014 02:14:19 GMT using RSA key ID 03FEDC60 # gpg: Can't check signature: public key not found * remotes/agraf/tags/signed-ppc-for-upstream: (130 commits) target-ppc: spapr: e500: fix to use cpu_dt_id target-ppc: add PowerPCCPU::cpu_dt_id target-ppc: Introduce hypervisor call H_GET_TCE target-ppc: Update ppc_hash64_store_hpte to support updating in-kernel htab target-ppc: Change the hpte store API target-ppc: Fix page table lookup with kvm enabled target-ppc: Fix htab_mask calculation target-ppc: Use Additional Temporary in stqcx Case target-ppc: Fix Compiler Warnings Due to 64-Bit Constants Declared as UL PPC: sPAPR: Only use getpagesize() when we run with kvm target-ppc/translate.c: Use ULL suffix for 64 bit constants spapr-vlan: flush queue whenever can_receive can go from false to true target-ppc: Altivec 2.07: Vector Permute and Exclusive OR target-ppc: Altivec 2.07: Vector SHA Sigma Instructions target-ppc: Altivec 2.07: AES Instructions target-ppc: Altivec 2.07: Binary Coded Decimal Instructions target-ppc: Altivec 2.07: Vector Polynomial Multiply Sum target-ppc: Altivec 2.07: Vector Gather Bits by Bytes target-ppc: Altivec 2.07: Doubleword Compares target-ppc: Altivec 2.07: vbpermq Instruction ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/scsi/spapr_vscsi.c')
-rw-r--r--hw/scsi/spapr_vscsi.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index e8bca390dd..b3835c821d 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -62,6 +62,8 @@
#define SRP_RSP_SENSE_DATA_LEN 18
+#define SRP_REPORT_LUNS_WLUN 0xc10100000000000ULL
+
typedef union vscsi_crq {
struct viosrp_crq s;
uint8_t raw[16];
@@ -719,12 +721,70 @@ static void vscsi_inquiry_no_target(VSCSIState *s, vscsi_req *req)
}
}
+static void vscsi_report_luns(VSCSIState *s, vscsi_req *req)
+{
+ BusChild *kid;
+ int i, len, n, rc;
+ uint8_t *resp_data;
+ bool found_lun0;
+
+ n = 0;
+ found_lun0 = false;
+ QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+ SCSIDevice *dev = SCSI_DEVICE(kid->child);
+
+ n += 8;
+ if (dev->channel == 0 && dev->id == 0 && dev->lun == 0) {
+ found_lun0 = true;
+ }
+ }
+ if (!found_lun0) {
+ n += 8;
+ }
+ len = n+8;
+
+ resp_data = g_malloc0(len);
+ memset(resp_data, 0, len);
+ stl_be_p(resp_data, n);
+ i = found_lun0 ? 8 : 16;
+ QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+ DeviceState *qdev = kid->child;
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
+
+ if (dev->id == 0 && dev->channel == 0) {
+ resp_data[i] = 0; /* Use simple LUN for 0 (SAM5 4.7.7.1) */
+ } else {
+ resp_data[i] = (2 << 6); /* Otherwise LUN addressing (4.7.7.4) */
+ }
+ resp_data[i] |= dev->id;
+ resp_data[i+1] = (dev->channel << 5);
+ resp_data[i+1] |= dev->lun;
+ i += 8;
+ }
+
+ vscsi_preprocess_desc(req);
+ rc = vscsi_srp_transfer_data(s, req, 0, resp_data, len);
+ g_free(resp_data);
+ if (rc < 0) {
+ vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
+ vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+ } else {
+ vscsi_send_rsp(s, req, 0, len - rc, 0);
+ }
+}
+
static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
{
union srp_iu *srp = &req->iu.srp;
SCSIDevice *sdev;
int n, lun;
+ if ((srp->cmd.lun == 0 || be64_to_cpu(srp->cmd.lun) == SRP_REPORT_LUNS_WLUN)
+ && srp->cmd.cdb[0] == REPORT_LUNS) {
+ vscsi_report_luns(s, req);
+ return 0;
+ }
+
sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
if (!sdev) {
DPRINTF("VSCSI: Command for lun %08" PRIx64 " with no drive\n",