static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req) { union srp_iu *srp = &req->iu.srp; SCSIDevice *sdev; int n, id, lun; vscsi_decode_id_lun(be64_to_cpu(srp->cmd.lun), &id, &lun); /* Qemu vs. linux issue with LUNs to be sorted out ... */ sdev = (id < 8 && lun < 16) ? s->bus.devs[id] : NULL; if (!sdev) { dprintf("VSCSI: Command for id %d with no drive\n", id); if (srp->cmd.cdb[0] == INQUIRY) { vscsi_inquiry_no_target(s, req); } else { vscsi_makeup_sense(s, req, ILLEGAL_REQUEST, 0x24, 0x00); vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0); } return 1; } req->sdev = sdev; req->lun = lun; n = sdev->info->send_command(sdev, req->qtag, srp->cmd.cdb, lun); dprintf("VSCSI: Queued command tag 0x%x CMD 0x%x ID %d LUN %d ret: %d\n", req->qtag, srp->cmd.cdb[0], id, lun, n); if (n) { /* Transfer direction must be set before preprocessing the * descriptors */ req->writing = (n < 1); /* Preprocess RDMA descriptors */ vscsi_preprocess_desc(req); } /* Get transfer direction and initiate transfer */ if (n > 0) { req->data_len = n; sdev->info->read_data(sdev, req->qtag); } else if (n < 0) { req->data_len = -n; sdev->info->write_data(sdev, req->qtag); } /* Don't touch req here, it may have been recycled already */ return 0; }