From patchwork Tue Jul 17 16:00:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 171497 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A76372C00BE for ; Wed, 18 Jul 2012 03:04:24 +1000 (EST) Received: from localhost ([::1]:51453 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SrADc-0007ir-4X for incoming@patchwork.ozlabs.org; Tue, 17 Jul 2012 12:01:48 -0400 Received: from eggs.gnu.org ([208.118.235.92]:38336) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SrACv-0006xw-Qd for qemu-devel@nongnu.org; Tue, 17 Jul 2012 12:01:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SrACm-0005lq-9P for qemu-devel@nongnu.org; Tue, 17 Jul 2012 12:01:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:64379) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SrACl-0005lh-VD for qemu-devel@nongnu.org; Tue, 17 Jul 2012 12:00:56 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q6HG0swl015900 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 17 Jul 2012 12:00:54 -0400 Received: from dhcp-5-188.str.redhat.com (vpn1-6-35.ams2.redhat.com [10.36.6.35]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q6HG0dqa007516; Tue, 17 Jul 2012 12:00:53 -0400 From: Kevin Wolf To: anthony@codemonkey.ws Date: Tue, 17 Jul 2012 18:00:04 +0200 Message-Id: <1342540838-9027-8-git-send-email-kwolf@redhat.com> In-Reply-To: <1342540838-9027-1-git-send-email-kwolf@redhat.com> References: <1342540838-9027-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 07/41] hd-geometry: Move disk geometry guessing back from block.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Markus Armbruster Commit f3d54fc4 factored it out of hw/ide.c for reuse. Sensible, except it was put into block.c. Device-specific functionality should be kept in device code, not the block layer. Move it to hw/hd-geometry.c, and make stylistic changes required to keep checkpatch.pl happy. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- block.c | 121 --------------------------------------- block.h | 1 - hw/Makefile.objs | 2 +- hw/block-common.h | 21 +++++++ hw/hd-geometry.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/ide/core.c | 3 +- hw/scsi-disk.c | 5 +- hw/virtio-blk.c | 3 +- 8 files changed, 191 insertions(+), 127 deletions(-) create mode 100644 hw/block-common.h create mode 100644 hw/hd-geometry.c diff --git a/block.c b/block.c index ffda1c2..06323cf 100644 --- a/block.c +++ b/block.c @@ -2132,127 +2132,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr) *nb_sectors_ptr = length; } -struct partition { - uint8_t boot_ind; /* 0x80 - active */ - uint8_t head; /* starting head */ - uint8_t sector; /* starting sector */ - uint8_t cyl; /* starting cylinder */ - uint8_t sys_ind; /* What partition type */ - uint8_t end_head; /* end head */ - uint8_t end_sector; /* end sector */ - uint8_t end_cyl; /* end cylinder */ - uint32_t start_sect; /* starting sector counting from 0 */ - uint32_t nr_sects; /* nr of sectors in partition */ -} QEMU_PACKED; - -/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ -static int guess_disk_lchs(BlockDriverState *bs, - int *pcylinders, int *pheads, int *psectors) -{ - uint8_t buf[BDRV_SECTOR_SIZE]; - int i, heads, sectors, cylinders; - struct partition *p; - uint32_t nr_sects; - uint64_t nb_sectors; - - bdrv_get_geometry(bs, &nb_sectors); - - /** - * The function will be invoked during startup not only in sync I/O mode, - * but also in async I/O mode. So the I/O throttling function has to - * be disabled temporarily here, not permanently. - */ - if (bdrv_read_unthrottled(bs, 0, buf, 1) < 0) { - return -1; - } - /* test msdos magic */ - if (buf[510] != 0x55 || buf[511] != 0xaa) - return -1; - for(i = 0; i < 4; i++) { - p = ((struct partition *)(buf + 0x1be)) + i; - nr_sects = le32_to_cpu(p->nr_sects); - if (nr_sects && p->end_head) { - /* We make the assumption that the partition terminates on - a cylinder boundary */ - heads = p->end_head + 1; - sectors = p->end_sector & 63; - if (sectors == 0) - continue; - cylinders = nb_sectors / (heads * sectors); - if (cylinders < 1 || cylinders > 16383) - continue; - *pheads = heads; - *psectors = sectors; - *pcylinders = cylinders; -#if 0 - printf("guessed geometry: LCHS=%d %d %d\n", - cylinders, heads, sectors); -#endif - return 0; - } - } - return -1; -} - -void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs) -{ - int translation, lba_detected = 0; - int cylinders, heads, secs; - uint64_t nb_sectors; - - /* if a geometry hint is available, use it */ - bdrv_get_geometry(bs, &nb_sectors); - bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs); - translation = bdrv_get_translation_hint(bs); - if (cylinders != 0) { - *pcyls = cylinders; - *pheads = heads; - *psecs = secs; - } else { - if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) { - if (heads > 16) { - /* if heads > 16, it means that a BIOS LBA - translation was active, so the default - hardware geometry is OK */ - lba_detected = 1; - goto default_geometry; - } else { - *pcyls = cylinders; - *pheads = heads; - *psecs = secs; - /* disable any translation to be in sync with - the logical geometry */ - if (translation == BIOS_ATA_TRANSLATION_AUTO) { - bdrv_set_translation_hint(bs, - BIOS_ATA_TRANSLATION_NONE); - } - } - } else { - default_geometry: - /* if no geometry, use a standard physical disk geometry */ - cylinders = nb_sectors / (16 * 63); - - if (cylinders > 16383) - cylinders = 16383; - else if (cylinders < 2) - cylinders = 2; - *pcyls = cylinders; - *pheads = 16; - *psecs = 63; - if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) { - if ((*pcyls * *pheads) <= 131072) { - bdrv_set_translation_hint(bs, - BIOS_ATA_TRANSLATION_LARGE); - } else { - bdrv_set_translation_hint(bs, - BIOS_ATA_TRANSLATION_LBA); - } - } - } - bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs); - } -} - void bdrv_set_geometry_hint(BlockDriverState *bs, int cyls, int heads, int secs) { diff --git a/block.h b/block.h index b24f664..993894e 100644 --- a/block.h +++ b/block.h @@ -178,7 +178,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset); int64_t bdrv_getlength(BlockDriverState *bs); int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); -void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs); int bdrv_commit(BlockDriverState *bs); int bdrv_commit_all(void); int bdrv_change_backing_file(BlockDriverState *bs, diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 9a350de..c3bdedc 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -138,7 +138,7 @@ common-obj-$(CONFIG_MAX111X) += max111x.o common-obj-$(CONFIG_DS1338) += ds1338.o common-obj-y += i2c.o smbus.o smbus_eeprom.o common-obj-y += eeprom93xx.o -common-obj-y += scsi-disk.o cdrom.o +common-obj-y += scsi-disk.o cdrom.o hd-geometry.o common-obj-y += scsi-generic.o scsi-bus.o common-obj-y += hid.o common-obj-$(CONFIG_SSI) += ssi.o diff --git a/hw/block-common.h b/hw/block-common.h new file mode 100644 index 0000000..3a4d4c6 --- /dev/null +++ b/hw/block-common.h @@ -0,0 +1,21 @@ +/* + * Common code for block device models + * + * Copyright (C) 2012 Red Hat, Inc. + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef HW_BLOCK_COMMON_H +#define HW_BLOCK_COMMON_H + +#include "qemu-common.h" + +/* Hard disk geometry */ + +void hd_geometry_guess(BlockDriverState *bs, + int *pcyls, int *pheads, int *psecs); + +#endif diff --git a/hw/hd-geometry.c b/hw/hd-geometry.c new file mode 100644 index 0000000..c45eafd --- /dev/null +++ b/hw/hd-geometry.c @@ -0,0 +1,162 @@ +/* + * Hard disk geometry utilities + * + * Copyright (C) 2012 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "block.h" +#include "hw/block-common.h" + +struct partition { + uint8_t boot_ind; /* 0x80 - active */ + uint8_t head; /* starting head */ + uint8_t sector; /* starting sector */ + uint8_t cyl; /* starting cylinder */ + uint8_t sys_ind; /* What partition type */ + uint8_t end_head; /* end head */ + uint8_t end_sector; /* end sector */ + uint8_t end_cyl; /* end cylinder */ + uint32_t start_sect; /* starting sector counting from 0 */ + uint32_t nr_sects; /* nr of sectors in partition */ +} QEMU_PACKED; + +/* try to guess the disk logical geometry from the MSDOS partition table. + Return 0 if OK, -1 if could not guess */ +static int guess_disk_lchs(BlockDriverState *bs, + int *pcylinders, int *pheads, int *psectors) +{ + uint8_t buf[BDRV_SECTOR_SIZE]; + int i, heads, sectors, cylinders; + struct partition *p; + uint32_t nr_sects; + uint64_t nb_sectors; + + bdrv_get_geometry(bs, &nb_sectors); + + /** + * The function will be invoked during startup not only in sync I/O mode, + * but also in async I/O mode. So the I/O throttling function has to + * be disabled temporarily here, not permanently. + */ + if (bdrv_read_unthrottled(bs, 0, buf, 1) < 0) { + return -1; + } + /* test msdos magic */ + if (buf[510] != 0x55 || buf[511] != 0xaa) { + return -1; + } + for (i = 0; i < 4; i++) { + p = ((struct partition *)(buf + 0x1be)) + i; + nr_sects = le32_to_cpu(p->nr_sects); + if (nr_sects && p->end_head) { + /* We make the assumption that the partition terminates on + a cylinder boundary */ + heads = p->end_head + 1; + sectors = p->end_sector & 63; + if (sectors == 0) { + continue; + } + cylinders = nb_sectors / (heads * sectors); + if (cylinders < 1 || cylinders > 16383) { + continue; + } + *pheads = heads; + *psectors = sectors; + *pcylinders = cylinders; +#if 0 + printf("guessed geometry: LCHS=%d %d %d\n", + cylinders, heads, sectors); +#endif + return 0; + } + } + return -1; +} + +void hd_geometry_guess(BlockDriverState *bs, + int *pcyls, int *pheads, int *psecs) +{ + int translation, lba_detected = 0; + int cylinders, heads, secs; + uint64_t nb_sectors; + + /* if a geometry hint is available, use it */ + bdrv_get_geometry(bs, &nb_sectors); + bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs); + translation = bdrv_get_translation_hint(bs); + if (cylinders != 0) { + *pcyls = cylinders; + *pheads = heads; + *psecs = secs; + } else { + if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) { + if (heads > 16) { + /* if heads > 16, it means that a BIOS LBA + translation was active, so the default + hardware geometry is OK */ + lba_detected = 1; + goto default_geometry; + } else { + *pcyls = cylinders; + *pheads = heads; + *psecs = secs; + /* disable any translation to be in sync with + the logical geometry */ + if (translation == BIOS_ATA_TRANSLATION_AUTO) { + bdrv_set_translation_hint(bs, + BIOS_ATA_TRANSLATION_NONE); + } + } + } else { + default_geometry: + /* if no geometry, use a standard physical disk geometry */ + cylinders = nb_sectors / (16 * 63); + + if (cylinders > 16383) { + cylinders = 16383; + } else if (cylinders < 2) { + cylinders = 2; + } + *pcyls = cylinders; + *pheads = 16; + *psecs = 63; + if ((lba_detected == 1) + && (translation == BIOS_ATA_TRANSLATION_AUTO)) { + if ((*pcyls * *pheads) <= 131072) { + bdrv_set_translation_hint(bs, + BIOS_ATA_TRANSLATION_LARGE); + } else { + bdrv_set_translation_hint(bs, + BIOS_ATA_TRANSLATION_LBA); + } + } + } + bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs); + } +} diff --git a/hw/ide/core.c b/hw/ide/core.c index 71d4d77..0d1bf10 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -30,6 +30,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "dma.h" +#include "hw/block-common.h" #include "blockdev.h" #include @@ -1933,7 +1934,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, s->drive_kind = kind; bdrv_get_geometry(bs, &nb_sectors); - bdrv_guess_geometry(bs, &cylinders, &heads, &secs); + hd_geometry_guess(bs, &cylinders, &heads, &secs); if (cylinders < 1 || cylinders > 16383) { error_report("cyls must be between 1 and 16383"); return -1; diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 34336b1..5339c2e 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -34,6 +34,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #include "scsi-defs.h" #include "sysemu.h" #include "blockdev.h" +#include "hw/block-common.h" #include "dma.h" #ifdef __linux @@ -989,7 +990,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf, break; } /* if a geometry hint is available, use it */ - bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs); + hd_geometry_guess(bdrv, &cylinders, &heads, &secs); p[2] = (cylinders >> 16) & 0xff; p[3] = (cylinders >> 8) & 0xff; p[4] = cylinders & 0xff; @@ -1023,7 +1024,7 @@ 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 */ - bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs); + hd_geometry_guess(bdrv, &cylinders, &heads, &secs); p[4] = heads & 0xff; p[5] = secs & 0xff; p[6] = s->qdev.blocksize >> 8; diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index fe07746..f16c5ce 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -14,6 +14,7 @@ #include "qemu-common.h" #include "qemu-error.h" #include "trace.h" +#include "hw/block-common.h" #include "blockdev.h" #include "virtio-blk.h" #include "scsi-defs.h" @@ -622,7 +623,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk) s->blk = blk; s->rq = NULL; s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; - bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); + hd_geometry_guess(s->bs, &cylinders, &heads, &secs); s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);