static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) { SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); SCSIDevice *s = r->req.dev; int ret; DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag, r->req.cmd.xfer, cmd[0]); #ifdef DEBUG_SCSI { int i; for (i = 1; i < r->req.cmd.len; i++) { printf(" 0x%02x", cmd[i]); } printf("\n"); } #endif if (r->req.cmd.xfer == 0) { if (r->buf != NULL) g_free(r->buf); r->buflen = 0; r->buf = NULL; /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete); if (ret < 0) { scsi_command_complete(r, ret); return 0; } return 0; } if (r->buflen != r->req.cmd.xfer) { if (r->buf != NULL) g_free(r->buf); r->buf = g_malloc(r->req.cmd.xfer); r->buflen = r->req.cmd.xfer; } memset(r->buf, 0, r->buflen); r->len = r->req.cmd.xfer; if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { r->len = 0; return -r->req.cmd.xfer; } else { return r->req.cmd.xfer; } }
/* Write data to a scsi device. Returns nonzero on failure. The transfer may complete asynchronously. */ static void scsi_write_data(SCSIRequest *req) { SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); SCSIDevice *s = r->req.dev; int ret; DPRINTF("scsi_write_data 0x%x\n", req->tag); if (r->len == 0) { r->len = r->buflen; scsi_req_data(&r->req, r->len); return; } /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete); if (ret < 0) { scsi_command_complete(r, ret); } }
/* Read more data from scsi device into buffer. */ static void scsi_read_data(SCSIRequest *req) { SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); SCSIDevice *s = r->req.dev; int ret; DPRINTF("scsi_read_data tag=0x%x\n", req->tag); /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); if (r->len == -1) { scsi_command_complete_noio(r, 0); return; } ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV, scsi_read_complete); if (ret < 0) { scsi_command_complete_noio(r, ret); } }