Revision b443ae67
b/hw/scsi-disk.c | ||
---|---|---|
65 | 65 |
uint32_t status; |
66 | 66 |
} SCSIDiskReq; |
67 | 67 |
|
68 |
typedef enum { SCSI_HD, SCSI_CD } SCSIDriveKind; |
|
69 |
|
|
68 | 70 |
struct SCSIDiskState |
69 | 71 |
{ |
70 | 72 |
SCSIDevice qdev; |
... | ... | |
78 | 80 |
char *version; |
79 | 81 |
char *serial; |
80 | 82 |
SCSISense sense; |
83 |
SCSIDriveKind drive_kind; |
|
81 | 84 |
}; |
82 | 85 |
|
83 | 86 |
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type); |
... | ... | |
406 | 409 |
return -1; |
407 | 410 |
} |
408 | 411 |
|
409 |
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
|
|
412 |
if (s->drive_kind == SCSI_CD) {
|
|
410 | 413 |
outbuf[buflen++] = 5; |
411 | 414 |
} else { |
412 | 415 |
outbuf[buflen++] = 0; |
... | ... | |
424 | 427 |
outbuf[buflen++] = 0x00; // list of supported pages (this page) |
425 | 428 |
outbuf[buflen++] = 0x80; // unit serial number |
426 | 429 |
outbuf[buflen++] = 0x83; // device identification |
427 |
if (bdrv_get_type_hint(s->bs) != BDRV_TYPE_CDROM) {
|
|
430 |
if (s->drive_kind == SCSI_HD) {
|
|
428 | 431 |
outbuf[buflen++] = 0xb0; // block limits |
429 | 432 |
outbuf[buflen++] = 0xb2; // thin provisioning |
430 | 433 |
} |
... | ... | |
477 | 480 |
unsigned int opt_io_size = |
478 | 481 |
s->qdev.conf.opt_io_size / s->qdev.blocksize; |
479 | 482 |
|
480 |
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
|
|
483 |
if (s->drive_kind == SCSI_CD) {
|
|
481 | 484 |
DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n", |
482 | 485 |
page_code); |
483 | 486 |
return -1; |
... | ... | |
547 | 550 |
return buflen; |
548 | 551 |
} |
549 | 552 |
|
550 |
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
|
|
553 |
if (s->drive_kind == SCSI_CD) {
|
|
551 | 554 |
outbuf[0] = 5; |
552 | 555 |
outbuf[1] = 0x80; |
553 | 556 |
memcpy(&outbuf[16], "QEMU CD-ROM ", 16); |
... | ... | |
678 | 681 |
return p[1] + 2; |
679 | 682 |
|
680 | 683 |
case 0x2a: /* CD Capabilities and Mechanical Status page. */ |
681 |
if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
|
|
684 |
if (s->drive_kind != SCSI_CD)
|
|
682 | 685 |
return 0; |
683 | 686 |
p[0] = 0x2a; |
684 | 687 |
p[1] = 0x14; |
... | ... | |
905 | 908 |
goto illegal_request; |
906 | 909 |
break; |
907 | 910 |
case START_STOP: |
908 |
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
|
|
911 |
if (s->drive_kind == SCSI_CD && (req->cmd.buf[4] & 2)) {
|
|
909 | 912 |
/* load/eject medium */ |
910 | 913 |
bdrv_eject(s->bs, !(req->cmd.buf[4] & 1)); |
911 | 914 |
} |
... | ... | |
1232 | 1235 |
blockdev_mark_auto_del(s->qdev.conf.bs); |
1233 | 1236 |
} |
1234 | 1237 |
|
1235 |
static int scsi_disk_initfn(SCSIDevice *dev)
|
|
1238 |
static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
|
|
1236 | 1239 |
{ |
1237 | 1240 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); |
1238 |
int is_cd; |
|
1239 | 1241 |
DriveInfo *dinfo; |
1240 | 1242 |
|
1241 | 1243 |
if (!s->qdev.conf.bs) { |
... | ... | |
1243 | 1245 |
return -1; |
1244 | 1246 |
} |
1245 | 1247 |
s->bs = s->qdev.conf.bs; |
1246 |
is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM;
|
|
1248 |
s->drive_kind = kind;
|
|
1247 | 1249 |
|
1248 |
if (!is_cd && !bdrv_is_inserted(s->bs)) {
|
|
1250 |
if (kind == SCSI_HD && !bdrv_is_inserted(s->bs)) {
|
|
1249 | 1251 |
error_report("Device needs media, but drive is empty"); |
1250 | 1252 |
return -1; |
1251 | 1253 |
} |
... | ... | |
1265 | 1267 |
return -1; |
1266 | 1268 |
} |
1267 | 1269 |
|
1268 |
if (is_cd) {
|
|
1270 |
if (kind == SCSI_CD) {
|
|
1269 | 1271 |
s->qdev.blocksize = 2048; |
1270 | 1272 |
} else { |
1271 | 1273 |
s->qdev.blocksize = s->qdev.conf.logical_block_size; |
... | ... | |
1275 | 1277 |
|
1276 | 1278 |
s->qdev.type = TYPE_DISK; |
1277 | 1279 |
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s); |
1278 |
bdrv_set_removable(s->bs, is_cd);
|
|
1280 |
bdrv_set_removable(s->bs, kind == SCSI_CD);
|
|
1279 | 1281 |
add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0"); |
1280 | 1282 |
return 0; |
1281 | 1283 |
} |
1282 | 1284 |
|
1283 |
static SCSIDeviceInfo scsi_disk_info = { |
|
1284 |
.qdev.name = "scsi-disk", |
|
1285 |
.qdev.fw_name = "disk", |
|
1286 |
.qdev.desc = "virtual scsi disk or cdrom", |
|
1287 |
.qdev.size = sizeof(SCSIDiskState), |
|
1288 |
.qdev.reset = scsi_disk_reset, |
|
1289 |
.init = scsi_disk_initfn, |
|
1290 |
.destroy = scsi_destroy, |
|
1291 |
.send_command = scsi_send_command, |
|
1292 |
.read_data = scsi_read_data, |
|
1293 |
.write_data = scsi_write_data, |
|
1294 |
.cancel_io = scsi_cancel_io, |
|
1295 |
.get_buf = scsi_get_buf, |
|
1296 |
.qdev.props = (Property[]) { |
|
1297 |
DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), |
|
1298 |
DEFINE_PROP_STRING("ver", SCSIDiskState, version), |
|
1299 |
DEFINE_PROP_STRING("serial", SCSIDiskState, serial), |
|
1300 |
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), |
|
1301 |
DEFINE_PROP_END_OF_LIST(), |
|
1302 |
}, |
|
1285 |
static int scsi_hd_initfn(SCSIDevice *dev) |
|
1286 |
{ |
|
1287 |
return scsi_initfn(dev, SCSI_HD); |
|
1288 |
} |
|
1289 |
|
|
1290 |
static int scsi_cd_initfn(SCSIDevice *dev) |
|
1291 |
{ |
|
1292 |
return scsi_initfn(dev, SCSI_CD); |
|
1293 |
} |
|
1294 |
|
|
1295 |
static int scsi_disk_initfn(SCSIDevice *dev) |
|
1296 |
{ |
|
1297 |
SCSIDriveKind kind; |
|
1298 |
|
|
1299 |
if (!dev->conf.bs) { |
|
1300 |
kind = SCSI_HD; /* will die in scsi_initfn() */ |
|
1301 |
} else { |
|
1302 |
kind = bdrv_get_type_hint(dev->conf.bs) == BDRV_TYPE_CDROM |
|
1303 |
? SCSI_CD : SCSI_HD; |
|
1304 |
} |
|
1305 |
|
|
1306 |
return scsi_initfn(dev, kind); |
|
1307 |
} |
|
1308 |
|
|
1309 |
#define DEFINE_SCSI_DISK_PROPERTIES() \ |
|
1310 |
DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \ |
|
1311 |
DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ |
|
1312 |
DEFINE_PROP_STRING("serial", SCSIDiskState, serial) |
|
1313 |
|
|
1314 |
static SCSIDeviceInfo scsi_disk_info[] = { |
|
1315 |
{ |
|
1316 |
.qdev.name = "scsi-hd", |
|
1317 |
.qdev.fw_name = "disk", |
|
1318 |
.qdev.desc = "virtual SCSI disk", |
|
1319 |
.qdev.size = sizeof(SCSIDiskState), |
|
1320 |
.qdev.reset = scsi_disk_reset, |
|
1321 |
.init = scsi_hd_initfn, |
|
1322 |
.destroy = scsi_destroy, |
|
1323 |
.send_command = scsi_send_command, |
|
1324 |
.read_data = scsi_read_data, |
|
1325 |
.write_data = scsi_write_data, |
|
1326 |
.cancel_io = scsi_cancel_io, |
|
1327 |
.get_buf = scsi_get_buf, |
|
1328 |
.qdev.props = (Property[]) { |
|
1329 |
DEFINE_SCSI_DISK_PROPERTIES(), |
|
1330 |
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), |
|
1331 |
DEFINE_PROP_END_OF_LIST(), |
|
1332 |
} |
|
1333 |
},{ |
|
1334 |
.qdev.name = "scsi-cd", |
|
1335 |
.qdev.fw_name = "disk", |
|
1336 |
.qdev.desc = "virtual SCSI CD-ROM", |
|
1337 |
.qdev.size = sizeof(SCSIDiskState), |
|
1338 |
.qdev.reset = scsi_disk_reset, |
|
1339 |
.init = scsi_cd_initfn, |
|
1340 |
.destroy = scsi_destroy, |
|
1341 |
.send_command = scsi_send_command, |
|
1342 |
.read_data = scsi_read_data, |
|
1343 |
.write_data = scsi_write_data, |
|
1344 |
.cancel_io = scsi_cancel_io, |
|
1345 |
.get_buf = scsi_get_buf, |
|
1346 |
.qdev.props = (Property[]) { |
|
1347 |
DEFINE_SCSI_DISK_PROPERTIES(), |
|
1348 |
DEFINE_PROP_END_OF_LIST(), |
|
1349 |
}, |
|
1350 |
},{ |
|
1351 |
.qdev.name = "scsi-disk", /* legacy -device scsi-disk */ |
|
1352 |
.qdev.fw_name = "disk", |
|
1353 |
.qdev.desc = "virtual SCSI disk or CD-ROM (legacy)", |
|
1354 |
.qdev.size = sizeof(SCSIDiskState), |
|
1355 |
.qdev.reset = scsi_disk_reset, |
|
1356 |
.init = scsi_disk_initfn, |
|
1357 |
.destroy = scsi_destroy, |
|
1358 |
.send_command = scsi_send_command, |
|
1359 |
.read_data = scsi_read_data, |
|
1360 |
.write_data = scsi_write_data, |
|
1361 |
.cancel_io = scsi_cancel_io, |
|
1362 |
.get_buf = scsi_get_buf, |
|
1363 |
.qdev.props = (Property[]) { |
|
1364 |
DEFINE_SCSI_DISK_PROPERTIES(), |
|
1365 |
DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), |
|
1366 |
DEFINE_PROP_END_OF_LIST(), |
|
1367 |
} |
|
1368 |
} |
|
1303 | 1369 |
}; |
1304 | 1370 |
|
1305 | 1371 |
static void scsi_disk_register_devices(void) |
1306 | 1372 |
{ |
1307 |
scsi_qdev_register(&scsi_disk_info); |
|
1373 |
int i; |
|
1374 |
|
|
1375 |
for (i = 0; i < ARRAY_SIZE(scsi_disk_info); i++) { |
|
1376 |
scsi_qdev_register(&scsi_disk_info[i]); |
|
1377 |
} |
|
1308 | 1378 |
} |
1309 | 1379 |
device_init(scsi_disk_register_devices) |
Also available in: Unified diff