aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi-disk.c
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2012-07-10 11:12:42 +0200
committerKevin Wolf <kwolf@redhat.com>2012-07-17 16:48:30 +0200
commitd252df489879ca3b128e080409b89305491d04cf (patch)
tree2b5b5c9379616aac66ba8b506a7385815e926cbe /hw/scsi-disk.c
parent1f24d7b47e1f18b5e7f0f050f915a42e9aa645db (diff)
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>
Diffstat (limited to 'hw/scsi-disk.c')
-rw-r--r--hw/scsi-disk.c69
1 files changed, 46 insertions, 23 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index c881acf011..0a182f987e 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -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_CAPABILITIES] = (1 << TYPE_ROM),
};
-
- BlockDriverState *bdrv = s->qdev.conf.bs;
- uint32_t cylinders, heads, secs;
uint8_t *p = *p_outbuf;
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;
}
/* if a geometry hint is available, use it */
- hd_geometry_guess(bdrv, &cylinders, &heads, &secs, NULL);
- p[2] = (cylinders >> 16) & 0xff;
- p[3] = (cylinders >> 8) & 0xff;
- p[4] = cylinders & 0xff;
- p[5] = heads & 0xff;
+ p[2] = (s->qdev.conf.cyls >> 16) & 0xff;
+ p[3] = (s->qdev.conf.cyls >> 8) & 0xff;
+ p[4] = s->qdev.conf.cyls & 0xff;
+ p[5] = s->qdev.conf.heads & 0xff;
/* Write precomp start cylinder, disabled */
- p[6] = (cylinders >> 16) & 0xff;
- p[7] = (cylinders >> 8) & 0xff;
- p[8] = cylinders & 0xff;
+ p[6] = (s->qdev.conf.cyls >> 16) & 0xff;
+ p[7] = (s->qdev.conf.cyls >> 8) & 0xff;
+ p[8] = s->qdev.conf.cyls & 0xff;
/* Reduced current start cylinder, disabled */
- p[9] = (cylinders >> 16) & 0xff;
- p[10] = (cylinders >> 8) & 0xff;
- p[11] = cylinders & 0xff;
+ p[9] = (s->qdev.conf.cyls >> 16) & 0xff;
+ p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
+ p[11] = s->qdev.conf.cyls & 0xff;
/* Device step rate [ns], 200ns */
p[12] = 0;
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[3] = 5000 & 0xff;
/* if a geometry hint is available, use it */
- hd_geometry_guess(bdrv, &cylinders, &heads, &secs, NULL);
- p[4] = heads & 0xff;
- p[5] = secs & 0xff;
+ p[4] = s->qdev.conf.heads & 0xff;
+ p[5] = s->qdev.conf.secs & 0xff;
p[6] = s->qdev.blocksize >> 8;
- p[8] = (cylinders >> 8) & 0xff;
- p[9] = cylinders & 0xff;
+ p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
+ p[9] = s->qdev.conf.cyls & 0xff;
/* Write precomp start cylinder, disabled */
- p[10] = (cylinders >> 8) & 0xff;
- p[11] = cylinders & 0xff;
+ p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
+ p[11] = s->qdev.conf.cyls & 0xff;
/* Reduced current start cylinder, disabled */
- p[12] = (cylinders >> 8) & 0xff;
- p[13] = cylinders & 0xff;
+ p[12] = (s->qdev.conf.cyls >> 8) & 0xff;
+ p[13] = s->qdev.conf.cyls & 0xff;
/* Device step rate [100us], 100us */
p[14] = 0;
p[15] = 1;
@@ -1755,6 +1750,33 @@ static int scsi_initfn(SCSIDevice *dev)
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) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
@@ -1975,6 +1997,7 @@ static Property scsi_hd_properties[] = {
DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
SCSI_DISK_F_DPOFUA, false),
DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
+ DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_END_OF_LIST(),
};