scsi-hd: qdev properties for disk geometry

Geometry needs to be qdev properties, because it belongs to the
disk's guest part.

Maintain backward compatibility exactly like for serial: fall back to
DriveInfo's geometry, set with -drive cyls=...

Do this only for scsi-hd.  scsi-disk is legacy.  scsi-cd doesn't have
a geometry.  scsi-block should get geometry from the host disk.

Bonus: info qtree now shows the geometry.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Markus Armbruster 2012-07-10 11:12:42 +02:00 committed by Kevin Wolf
parent 1f24d7b47e
commit d252df4898

View File

@ -966,9 +966,6 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
[MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM), [MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM),
[MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM), [MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM),
}; };
BlockDriverState *bdrv = s->qdev.conf.bs;
uint32_t cylinders, heads, secs;
uint8_t *p = *p_outbuf; uint8_t *p = *p_outbuf;
if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) { if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
@ -990,19 +987,18 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
break; break;
} }
/* if a geometry hint is available, use it */ /* if a geometry hint is available, use it */
hd_geometry_guess(bdrv, &cylinders, &heads, &secs, NULL); p[2] = (s->qdev.conf.cyls >> 16) & 0xff;
p[2] = (cylinders >> 16) & 0xff; p[3] = (s->qdev.conf.cyls >> 8) & 0xff;
p[3] = (cylinders >> 8) & 0xff; p[4] = s->qdev.conf.cyls & 0xff;
p[4] = cylinders & 0xff; p[5] = s->qdev.conf.heads & 0xff;
p[5] = heads & 0xff;
/* Write precomp start cylinder, disabled */ /* Write precomp start cylinder, disabled */
p[6] = (cylinders >> 16) & 0xff; p[6] = (s->qdev.conf.cyls >> 16) & 0xff;
p[7] = (cylinders >> 8) & 0xff; p[7] = (s->qdev.conf.cyls >> 8) & 0xff;
p[8] = cylinders & 0xff; p[8] = s->qdev.conf.cyls & 0xff;
/* Reduced current start cylinder, disabled */ /* Reduced current start cylinder, disabled */
p[9] = (cylinders >> 16) & 0xff; p[9] = (s->qdev.conf.cyls >> 16) & 0xff;
p[10] = (cylinders >> 8) & 0xff; p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
p[11] = cylinders & 0xff; p[11] = s->qdev.conf.cyls & 0xff;
/* Device step rate [ns], 200ns */ /* Device step rate [ns], 200ns */
p[12] = 0; p[12] = 0;
p[13] = 200; p[13] = 200;
@ -1024,18 +1020,17 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
p[2] = 5000 >> 8; p[2] = 5000 >> 8;
p[3] = 5000 & 0xff; p[3] = 5000 & 0xff;
/* if a geometry hint is available, use it */ /* if a geometry hint is available, use it */
hd_geometry_guess(bdrv, &cylinders, &heads, &secs, NULL); p[4] = s->qdev.conf.heads & 0xff;
p[4] = heads & 0xff; p[5] = s->qdev.conf.secs & 0xff;
p[5] = secs & 0xff;
p[6] = s->qdev.blocksize >> 8; p[6] = s->qdev.blocksize >> 8;
p[8] = (cylinders >> 8) & 0xff; p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
p[9] = cylinders & 0xff; p[9] = s->qdev.conf.cyls & 0xff;
/* Write precomp start cylinder, disabled */ /* Write precomp start cylinder, disabled */
p[10] = (cylinders >> 8) & 0xff; p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
p[11] = cylinders & 0xff; p[11] = s->qdev.conf.cyls & 0xff;
/* Reduced current start cylinder, disabled */ /* Reduced current start cylinder, disabled */
p[12] = (cylinders >> 8) & 0xff; p[12] = (s->qdev.conf.cyls >> 8) & 0xff;
p[13] = cylinders & 0xff; p[13] = s->qdev.conf.cyls & 0xff;
/* Device step rate [100us], 100us */ /* Device step rate [100us], 100us */
p[14] = 0; p[14] = 0;
p[15] = 1; p[15] = 1;
@ -1755,6 +1750,33 @@ static int scsi_initfn(SCSIDevice *dev)
return -1; return -1;
} }
if (!dev->conf.cyls && !dev->conf.heads && !dev->conf.secs) {
/* try to fall back to value set with legacy -drive cyls=... */
dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
dev->conf.cyls = dinfo->cyls;
dev->conf.heads = dinfo->heads;
dev->conf.secs = dinfo->secs;
}
if (!dev->conf.cyls && !dev->conf.heads && !dev->conf.secs) {
hd_geometry_guess(s->qdev.conf.bs,
&dev->conf.cyls, &dev->conf.heads, &dev->conf.secs,
NULL);
}
if (dev->conf.cyls || dev->conf.heads || dev->conf.secs) {
if (dev->conf.cyls < 1 || dev->conf.cyls > 65535) {
error_report("cyls must be between 1 and 65535");
return -1;
}
if (dev->conf.heads < 1 || dev->conf.heads > 255) {
error_report("heads must be between 1 and 255");
return -1;
}
if (dev->conf.secs < 1 || dev->conf.secs > 255) {
error_report("secs must be between 1 and 255");
return -1;
}
}
if (!s->serial) { if (!s->serial) {
/* try to fall back to value set with legacy -drive serial=... */ /* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(s->qdev.conf.bs); dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
@ -1975,6 +1997,7 @@ static Property scsi_hd_properties[] = {
DEFINE_PROP_BIT("dpofua", SCSIDiskState, features, DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
SCSI_DISK_F_DPOFUA, false), SCSI_DISK_F_DPOFUA, false),
DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0), DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };