mirror of https://github.com/xemu-project/xemu.git
scsi: Implement 'get_sense' callback
The get_sense callback copies existing sense information into the provided buffer. This is required if sense information should be transferred together with the command response. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
0c34459b6a
commit
74382217ca
|
@ -156,6 +156,15 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req)
|
||||||
return req->dev->info->get_buf(req);
|
return req->dev->info->get_buf(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
if (req->dev->info->get_sense) {
|
||||||
|
return req->dev->info->get_sense(req, buf, len);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t scsi_req_enqueue(SCSIRequest *req, uint8_t *buf)
|
int32_t scsi_req_enqueue(SCSIRequest *req, uint8_t *buf)
|
||||||
{
|
{
|
||||||
int32_t rc;
|
int32_t rc;
|
||||||
|
|
|
@ -340,6 +340,14 @@ static uint8_t *scsi_get_buf(SCSIRequest *req)
|
||||||
return (uint8_t *)r->iov.iov_base;
|
return (uint8_t *)r->iov.iov_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy sense information into the provided buffer */
|
||||||
|
static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
|
||||||
|
{
|
||||||
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
||||||
|
|
||||||
|
return scsi_build_sense(s->sense, outbuf, len, len > 14);
|
||||||
|
}
|
||||||
|
|
||||||
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||||
{
|
{
|
||||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
||||||
|
@ -1257,6 +1265,7 @@ static SCSIDeviceInfo scsi_disk_info[] = {
|
||||||
.write_data = scsi_write_data,
|
.write_data = scsi_write_data,
|
||||||
.cancel_io = scsi_cancel_io,
|
.cancel_io = scsi_cancel_io,
|
||||||
.get_buf = scsi_get_buf,
|
.get_buf = scsi_get_buf,
|
||||||
|
.get_sense = scsi_get_sense,
|
||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
DEFINE_SCSI_DISK_PROPERTIES(),
|
DEFINE_SCSI_DISK_PROPERTIES(),
|
||||||
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
|
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
|
||||||
|
@ -1277,6 +1286,7 @@ static SCSIDeviceInfo scsi_disk_info[] = {
|
||||||
.write_data = scsi_write_data,
|
.write_data = scsi_write_data,
|
||||||
.cancel_io = scsi_cancel_io,
|
.cancel_io = scsi_cancel_io,
|
||||||
.get_buf = scsi_get_buf,
|
.get_buf = scsi_get_buf,
|
||||||
|
.get_sense = scsi_get_sense,
|
||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
DEFINE_SCSI_DISK_PROPERTIES(),
|
DEFINE_SCSI_DISK_PROPERTIES(),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
@ -1296,6 +1306,7 @@ static SCSIDeviceInfo scsi_disk_info[] = {
|
||||||
.write_data = scsi_write_data,
|
.write_data = scsi_write_data,
|
||||||
.cancel_io = scsi_cancel_io,
|
.cancel_io = scsi_cancel_io,
|
||||||
.get_buf = scsi_get_buf,
|
.get_buf = scsi_get_buf,
|
||||||
|
.get_sense = scsi_get_sense,
|
||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
DEFINE_SCSI_DISK_PROPERTIES(),
|
DEFINE_SCSI_DISK_PROPERTIES(),
|
||||||
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
|
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
|
||||||
|
|
|
@ -79,6 +79,23 @@ static void scsi_clear_sense(SCSIGenericState *s)
|
||||||
s->driver_status = 0;
|
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)
|
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
|
||||||
{
|
{
|
||||||
SCSIRequest *req;
|
SCSIRequest *req;
|
||||||
|
@ -535,6 +552,7 @@ static SCSIDeviceInfo scsi_generic_info = {
|
||||||
.write_data = scsi_write_data,
|
.write_data = scsi_write_data,
|
||||||
.cancel_io = scsi_cancel_io,
|
.cancel_io = scsi_cancel_io,
|
||||||
.get_buf = scsi_get_buf,
|
.get_buf = scsi_get_buf,
|
||||||
|
.get_sense = scsi_get_sense,
|
||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
|
DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
|
|
@ -80,6 +80,7 @@ struct SCSIDeviceInfo {
|
||||||
int (*write_data)(SCSIRequest *req);
|
int (*write_data)(SCSIRequest *req);
|
||||||
void (*cancel_io)(SCSIRequest *req);
|
void (*cancel_io)(SCSIRequest *req);
|
||||||
uint8_t *(*get_buf)(SCSIRequest *req);
|
uint8_t *(*get_buf)(SCSIRequest *req);
|
||||||
|
int (*get_sense)(SCSIRequest *req, uint8_t *buf, int len);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SCSIBusOps {
|
struct SCSIBusOps {
|
||||||
|
@ -155,6 +156,7 @@ void scsi_req_continue(SCSIRequest *req);
|
||||||
void scsi_req_data(SCSIRequest *req, int len);
|
void scsi_req_data(SCSIRequest *req, int len);
|
||||||
void scsi_req_complete(SCSIRequest *req);
|
void scsi_req_complete(SCSIRequest *req);
|
||||||
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
||||||
|
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
||||||
void scsi_req_abort(SCSIRequest *req, int status);
|
void scsi_req_abort(SCSIRequest *req, int status);
|
||||||
void scsi_req_cancel(SCSIRequest *req);
|
void scsi_req_cancel(SCSIRequest *req);
|
||||||
void scsi_device_purge_requests(SCSIDevice *sdev);
|
void scsi_device_purge_requests(SCSIDevice *sdev);
|
||||||
|
|
|
@ -450,6 +450,15 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
|
||||||
uint8_t *cdb = req->iu.srp.cmd.cdb;
|
uint8_t *cdb = req->iu.srp.cmd.cdb;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
n = scsi_req_get_sense(req->sreq, req->sense, sizeof(req->sense));
|
||||||
|
if (n) {
|
||||||
|
req->senselen = n;
|
||||||
|
vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
|
||||||
|
vscsi_put_req(s, req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("VSCSI: Got CHECK_CONDITION, requesting sense...\n");
|
||||||
cdb[0] = 3;
|
cdb[0] = 3;
|
||||||
cdb[1] = 0;
|
cdb[1] = 0;
|
||||||
cdb[2] = 0;
|
cdb[2] = 0;
|
||||||
|
@ -522,7 +531,6 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
|
||||||
}
|
}
|
||||||
vscsi_send_rsp(s, req, 0, res_in, res_out);
|
vscsi_send_rsp(s, req, 0, res_in, res_out);
|
||||||
} else if (arg == CHECK_CONDITION) {
|
} else if (arg == CHECK_CONDITION) {
|
||||||
dprintf("VSCSI: Got CHECK_CONDITION, requesting sense...\n");
|
|
||||||
vscsi_send_request_sense(s, req);
|
vscsi_send_request_sense(s, req);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue