#include "hw.h"
-#include "sysemu.h"
+#include "qemu-error.h"
#include "scsi.h"
#include "scsi-defs.h"
-#include "block.h"
#include "qdev.h"
+#include "blockdev.h"
static struct BusInfo scsi_bus_info = {
.name = "SCSI",
}
}
if (dev->id >= bus->ndev) {
- qemu_error("bad scsi device id: %d\n", dev->id);
+ error_report("bad scsi device id: %d", dev->id);
goto err;
}
}
/* handle legacy '-drive if=scsi,...' cmd line args */
-/* FIXME callers should check for failure, but don't */
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit)
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit)
{
const char *driver;
DeviceState *dev;
- driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk";
+ driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
dev = qdev_create(&bus->qbus, driver);
qdev_prop_set_uint32(dev, "scsi-id", unit);
- qdev_prop_set_drive(dev, "drive", dinfo);
+ if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
+ qdev_free(dev);
+ return NULL;
+ }
if (qdev_init(dev) < 0)
return NULL;
return DO_UPCAST(SCSIDevice, qdev, dev);
}
-void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
+int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
{
+ Location loc;
DriveInfo *dinfo;
- int unit;
+ int res = 0, unit;
+ loc_push_none(&loc);
for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
dinfo = drive_get(IF_SCSI, bus->busnr, unit);
if (dinfo == NULL) {
continue;
}
- scsi_bus_legacy_add_drive(bus, dinfo, unit);
+ qemu_opts_loc_restore(dinfo->opts);
+ if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit)) {
+ res = -1;
+ break;
+ }
}
+ loc_pop(&loc);
+ return res;
}
void scsi_dev_clear_sense(SCSIDevice *dev)
req->tag = tag;
req->lun = lun;
req->status = -1;
+ req->enqueued = true;
QTAILQ_INSERT_TAIL(&d->requests, req, next);
return req;
}
return NULL;
}
+static void scsi_req_dequeue(SCSIRequest *req)
+{
+ if (req->enqueued) {
+ QTAILQ_REMOVE(&req->dev->requests, req, next);
+ req->enqueued = false;
+ }
+}
+
void scsi_req_free(SCSIRequest *req)
{
- QTAILQ_REMOVE(&req->dev->requests, req, next);
+ scsi_req_dequeue(req);
qemu_free(req);
}
case INQUIRY:
req->cmd.xfer = cmd[4] | (cmd[3] << 8);
break;
+ case MAINTENANCE_OUT:
+ case MAINTENANCE_IN:
+ if (req->dev->type == TYPE_ROM) {
+ /* GPCMD_REPORT_KEY and GPCMD_SEND_KEY from multi media commands */
+ req->cmd.xfer = cmd[9] | (cmd[8] << 8);
+ }
+ break;
}
return 0;
}
case MEDIUM_SCAN:
case SEND_VOLUME_TAG:
case WRITE_LONG_2:
+ case PERSISTENT_RESERVE_OUT:
+ case MAINTENANCE_OUT:
req->cmd.mode = SCSI_XFER_TO_DEV;
break;
default:
static const char *names[] = {
[ TEST_UNIT_READY ] = "TEST_UNIT_READY",
[ REZERO_UNIT ] = "REZERO_UNIT",
+ /* REWIND and REZERO_UNIT use the same operation code */
[ REQUEST_SENSE ] = "REQUEST_SENSE",
[ FORMAT_UNIT ] = "FORMAT_UNIT",
[ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
[ SPACE ] = "SPACE",
[ INQUIRY ] = "INQUIRY",
[ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
+ [ MAINTENANCE_IN ] = "MAINTENANCE_IN",
+ [ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
[ MODE_SELECT ] = "MODE_SELECT",
[ RESERVE ] = "RESERVE",
[ RELEASE ] = "RELEASE",
[ SEARCH_LOW ] = "SEARCH_LOW",
[ SET_LIMITS ] = "SET_LIMITS",
[ PRE_FETCH ] = "PRE_FETCH",
- [ READ_POSITION ] = "READ_POSITION",
+ /* READ_POSITION and PRE_FETCH use the same operation code */
[ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
[ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
[ READ_DEFECT_DATA ] = "READ_DEFECT_DATA",
[ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG",
[ WRITE_LONG_2 ] = "WRITE_LONG_2",
- [ REWIND ] = "REWIND",
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
[ READ_16 ] = "READ_16",
void scsi_req_complete(SCSIRequest *req)
{
assert(req->status != -1);
+ scsi_req_dequeue(req);
req->bus->complete(req->bus, SCSI_REASON_DONE,
req->tag,
req->status);