func: static void vscsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
  
                                     uint32_t arg)
  
  {
  
      VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, bus->qbus.parent);
  
      vscsi_req *req = vscsi_find_req(s, tag);
  
      SCSIDevice *sdev;
  
      uint8_t *buf;
  
      int32_t res_in = 0, res_out = 0;
  
      int len, rc = 0;
  
  
  
      dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x arg=0x%x, req=%p\n",
  
              reason, tag, arg, req);
  
      if (req == NULL) {
  
          fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", tag);
  
          return;
  
      }
  
      sdev = req->sdev;
  
  
  
      if (req->sensing) {
  
          if (reason == SCSI_REASON_DONE) {
  
              dprintf("VSCSI: Sense done !\n");
  
              vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
  
              vscsi_put_req(s, req);
  
          } else {
  
              uint8_t *buf = sdev->info->get_buf(sdev, tag);
  
  
  
              len = MIN(arg, SCSI_SENSE_BUF_SIZE);
  
              dprintf("VSCSI: Sense data, %d bytes:\n", len);
  
              dprintf("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
  
                      buf[0], buf[1], buf[2], buf[3],
  
                      buf[4], buf[5], buf[6], buf[7]);
  
              dprintf("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
  
                      buf[8], buf[9], buf[10], buf[11],
  
                      buf[12], buf[13], buf[14], buf[15]);
  
              memcpy(req->sense, buf, len);
  
              req->senselen = len;
  
              sdev->info->read_data(sdev, req->qtag);
  
          }
  
          return;
  
      }
  
  
  
      if (reason == SCSI_REASON_DONE) {
  
          dprintf("VSCSI: Command complete err=%d\n", arg);
  
          if (arg == 0) {
  
              /* We handle overflows, not underflows for normal commands,
  
               * but hopefully nobody cares
  
               */
  
              if (req->writing) {
  
                  res_out = req->data_len;
  
              } else {
  
                  res_in = req->data_len;
  
              }
  
              vscsi_send_rsp(s, req, 0, res_in, res_out);
  
          } else if (arg == CHECK_CONDITION) {
  
              dprintf("VSCSI: Got CHECK_CONDITION, requesting sense...\n");
  
              vscsi_send_request_sense(s, req);
  
              return;
  
          } else {
  
              vscsi_send_rsp(s, req, arg, 0, 0);
  
          }
  
          vscsi_put_req(s, req);
  
          return;
  
      }
  
  
  
      /* "arg" is how much we have read for reads and how much we want
  
       * to write for writes (ie, how much is to be DMA'd)
  
       */
  
      if (arg) {
  
          buf = sdev->info->get_buf(sdev, tag);
  
          rc = vscsi_srp_transfer_data(s, req, req->writing, buf, arg);
  
      }
  
      if (rc < 0) {
  
          fprintf(stderr, "VSCSI: RDMA error rc=%d!\n", rc);
  
          sdev->info->cancel_io(sdev, req->qtag);
  
          vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
  
          vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
  
          vscsi_put_req(s, req);
  
          return;
  
      }
  
  
  
      /* Start next chunk */
  
      req->data_len -= rc;
  
      if (req->writing) {
  
          sdev->info->write_data(sdev, req->qtag);
  
      } else {
  
          sdev->info->read_data(sdev, req->qtag);
  
      }
  
  }
  