From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Izx3R-0003sS-Ac for qemu-devel@nongnu.org; Wed, 05 Dec 2007 11:24:57 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Izx3O-0003op-6F for qemu-devel@nongnu.org; Wed, 05 Dec 2007 11:24:56 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Izx3N-0003oa-UY for qemu-devel@nongnu.org; Wed, 05 Dec 2007 11:24:53 -0500 Received: from e3.ny.us.ibm.com ([32.97.182.143]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Izx3N-0005qV-FS for qemu-devel@nongnu.org; Wed, 05 Dec 2007 11:24:53 -0500 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by e3.ny.us.ibm.com (8.13.8/8.13.8) with ESMTP id lB5GOjKp031939 for ; Wed, 5 Dec 2007 11:24:45 -0500 Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay02.pok.ibm.com (8.13.8/8.13.8/NCO v8.7) with ESMTP id lB5GOjXF447202 for ; Wed, 5 Dec 2007 11:24:45 -0500 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id lB5GOj3I012217 for ; Wed, 5 Dec 2007 11:24:45 -0500 Received: from [9.67.7.111] (wecm-9-67-7-111.wecm.ibm.com [9.67.7.111]) by d01av04.pok.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id lB5GOiib012108 for ; Wed, 5 Dec 2007 11:24:44 -0500 Message-ID: <4756D0CA.3030105@us.ibm.com> Date: Wed, 05 Dec 2007 10:24:42 -0600 From: Anthony Liguori MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------070705010605000003010808" Subject: [Qemu-devel] [PATCH 1/2] Refactor CHS guessing to be usable outside of IDE Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------070705010605000003010808 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit The next patch I post will require this patch. It refactors the CHS guessing so it can be used by devices other than IDE. Regards, Anthony Liguori --------------070705010605000003010808 Content-Type: text/x-patch; name="bdrv-guess-geometry.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="bdrv-guess-geometry.diff" Index: qemu/block.c =================================================================== --- qemu.orig/block.c 2007-12-04 16:18:46.000000000 -0600 +++ qemu/block.c 2007-12-04 16:19:08.000000000 -0600 @@ -738,6 +738,122 @@ memset(bs->boot_sector_data + size, 0, 512 - size); } +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 */ +} __attribute__((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[512]; + int ret, i, heads, sectors, cylinders; + struct partition *p; + uint32_t nr_sects; + int64_t nb_sectors; + + bdrv_get_geometry(bs, &nb_sectors); + + ret = bdrv_read(bs, 0, buf, 1); + if (ret < 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; + int64_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) { Index: qemu/block.h =================================================================== --- qemu.orig/block.h 2007-12-04 16:18:46.000000000 -0600 +++ qemu/block.h 2007-12-04 16:19:08.000000000 -0600 @@ -73,6 +73,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset); int64_t bdrv_getlength(BlockDriverState *bs); void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr); +void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs); int bdrv_commit(BlockDriverState *bs); void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); /* async block I/O */ Index: qemu/hw/ide.c =================================================================== --- qemu.orig/hw/ide.c 2007-12-04 16:18:46.000000000 -0600 +++ qemu/hw/ide.c 2007-12-04 16:19:08.000000000 -0600 @@ -2355,67 +2355,13 @@ s->media_changed = 0; } -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 */ -} __attribute__((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(IDEState *s, - int *pcylinders, int *pheads, int *psectors) -{ - uint8_t buf[512]; - int ret, i, heads, sectors, cylinders; - struct partition *p; - uint32_t nr_sects; - - ret = bdrv_read(s->bs, 0, buf, 1); - if (ret < 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 = s->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; -} - static void ide_init2(IDEState *ide_state, BlockDriverState *hd0, BlockDriverState *hd1, qemu_irq irq) { IDEState *s; static int drive_serial = 1; - int i, cylinders, heads, secs, translation, lba_detected = 0; + int i, cylinders, heads, secs; int64_t nb_sectors; for(i = 0; i < 2; i++) { @@ -2426,56 +2372,12 @@ s->bs = hd1; if (s->bs) { bdrv_get_geometry(s->bs, &nb_sectors); + bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); + s->cylinders = cylinders; + s->heads = heads; + s->sectors = secs; s->nb_sectors = nb_sectors; - /* if a geometry hint is available, use it */ - bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); - translation = bdrv_get_translation_hint(s->bs); - if (cylinders != 0) { - s->cylinders = cylinders; - s->heads = heads; - s->sectors = secs; - } else { - if (guess_disk_lchs(s, &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 { - s->cylinders = cylinders; - s->heads = heads; - s->sectors = secs; - /* disable any translation to be in sync with - the logical geometry */ - if (translation == BIOS_ATA_TRANSLATION_AUTO) { - bdrv_set_translation_hint(s->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; - s->cylinders = cylinders; - s->heads = 16; - s->sectors = 63; - if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) { - if ((s->cylinders * s->heads) <= 131072) { - bdrv_set_translation_hint(s->bs, - BIOS_ATA_TRANSLATION_LARGE); - } else { - bdrv_set_translation_hint(s->bs, - BIOS_ATA_TRANSLATION_LBA); - } - } - } - bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors); - } + if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { s->is_cdrom = 1; bdrv_set_change_cb(s->bs, cdrom_change_cb, s); --------------070705010605000003010808--