s->driver_status = 0;
}
+static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
+{
+ SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
+ int size = SCSI_SENSE_BUF_SIZE;
+
+ if (!(s->driver_status & SG_ERR_DRIVER_SENSE)) {
+ size = scsi_build_sense(SENSE_CODE(NO_SENSE), s->sensebuf,
+ SCSI_SENSE_BUF_SIZE, 0);
+ }
+ if (size > len) {
+ size = len;
+ }
+ memcpy(outbuf, s->sensebuf, size);
+
+ return size;
+}
+
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
{
SCSIRequest *req;
if (ret != 0) {
switch (ret) {
+ case -EDOM:
+ r->req.status = TASK_SET_FULL;
+ break;
case -EINVAL:
r->req.status = CHECK_CONDITION;
scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
/* Write data to a scsi device. Returns nonzero on failure.
The transfer may complete asynchronously. */
-static int scsi_write_data(SCSIRequest *req)
+static void scsi_write_data(SCSIRequest *req)
{
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
if (r->len == 0) {
r->len = r->buflen;
scsi_req_data(&r->req, r->len);
- return 0;
+ return;
}
ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
if (ret < 0) {
scsi_command_complete(r, ret);
- return 1;
}
-
- return 0;
}
/* Return a pointer to the data buffer. */
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
int ret;
- if (cmd[0] != REQUEST_SENSE &&
- (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
- DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
+ if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
+ DPRINTF("Unimplemented LUN %d\n", req->lun);
scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
r->req.status = CHECK_CONDITION;
scsi_req_complete(&r->req);
.write_data = scsi_write_data,
.cancel_io = scsi_cancel_io,
.get_buf = scsi_get_buf,
+ .get_sense = scsi_get_sense,
.qdev.props = (Property[]) {
DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
DEFINE_PROP_END_OF_LIST(),