scsi: add SCSIDevice vmstate definitions

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2011-12-02 16:27:02 +01:00
parent 5d0d246792
commit 63f740dd9e
2 changed files with 120 additions and 3 deletions

View File

@ -647,10 +647,8 @@ void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
req->sense_len = 18;
}
int32_t scsi_req_enqueue(SCSIRequest *req)
static void scsi_req_enqueue_internal(SCSIRequest *req)
{
int32_t rc;
assert(!req->enqueued);
scsi_req_ref(req);
if (req->bus->info->get_sg_list) {
@ -660,7 +658,14 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
}
req->enqueued = true;
QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
}
int32_t scsi_req_enqueue(SCSIRequest *req)
{
int32_t rc;
assert(!req->retry);
scsi_req_enqueue_internal(req);
scsi_req_ref(req);
rc = req->ops->send_command(req, req->cmd.buf);
scsi_req_unref(req);
@ -1442,6 +1447,102 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
return target_dev;
}
/* SCSI request list. For simplicity, pv points to the whole device */
static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
{
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
SCSIRequest *req;
QTAILQ_FOREACH(req, &s->requests, next) {
assert(!req->io_canceled);
assert(req->status == -1);
assert(req->retry);
assert(req->enqueued);
qemu_put_sbyte(f, 1);
qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
qemu_put_be32s(f, &req->tag);
qemu_put_be32s(f, &req->lun);
if (bus->info->save_request) {
bus->info->save_request(f, req);
}
if (req->ops->save_request) {
req->ops->save_request(f, req);
}
}
qemu_put_sbyte(f, 0);
}
static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
{
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
while (qemu_get_sbyte(f)) {
uint8_t buf[SCSI_CMD_BUF_SIZE];
uint32_t tag;
uint32_t lun;
SCSIRequest *req;
qemu_get_buffer(f, buf, sizeof(buf));
qemu_get_be32s(f, &tag);
qemu_get_be32s(f, &lun);
req = scsi_req_new(s, tag, lun, buf, NULL);
if (bus->info->load_request) {
req->hba_private = bus->info->load_request(f, req);
}
if (req->ops->load_request) {
req->ops->load_request(f, req);
}
/* Just restart it later. */
req->retry = true;
scsi_req_enqueue_internal(req);
/* At this point, the request will be kept alive by the reference
* added by scsi_req_enqueue_internal, so we can release our reference.
* The HBA of course will add its own reference in the load_request
* callback if it needs to hold on the SCSIRequest.
*/
scsi_req_unref(req);
}
return 0;
}
const VMStateInfo vmstate_info_scsi_requests = {
.name = "scsi-requests",
.get = get_scsi_requests,
.put = put_scsi_requests,
};
const VMStateDescription vmstate_scsi_device = {
.name = "SCSIDevice",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(unit_attention.key, SCSIDevice),
VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
VMSTATE_BOOL(sense_is_ua, SCSIDevice),
VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE),
VMSTATE_UINT32(sense_len, SCSIDevice),
{
.name = "requests",
.version_id = 0,
.field_exists = NULL,
.size = 0, /* ouch */
.info = &vmstate_info_scsi_requests,
.flags = VMS_SINGLE,
.offset = 0,
},
VMSTATE_END_OF_LIST()
}
};
static void scsi_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);

View File

@ -96,6 +96,16 @@ struct SCSIDevice
uint64_t max_lba;
};
extern const VMStateDescription vmstate_scsi_device;
#define VMSTATE_SCSI_DEVICE(_field, _state) { \
.name = (stringify(_field)), \
.size = sizeof(SCSIDevice), \
.vmsd = &vmstate_scsi_device, \
.flags = VMS_STRUCT, \
.offset = vmstate_offset_value(_state, _field, SCSIDevice), \
}
/* cdrom.c */
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
@ -109,6 +119,9 @@ struct SCSIReqOps {
void (*write_data)(SCSIRequest *req);
void (*cancel_io)(SCSIRequest *req);
uint8_t *(*get_buf)(SCSIRequest *req);
void (*save_request)(QEMUFile *f, SCSIRequest *req);
void (*load_request)(QEMUFile *f, SCSIRequest *req);
};
struct SCSIBusInfo {
@ -118,6 +131,9 @@ struct SCSIBusInfo {
void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
void (*cancel)(SCSIRequest *req);
QEMUSGList *(*get_sg_list)(SCSIRequest *req);
void (*save_request)(QEMUFile *f, SCSIRequest *req);
void *(*load_request)(QEMUFile *f, SCSIRequest *req);
};
struct SCSIBus {