From: Anthony Liguori <aliguori@us.ibm.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 1/2] Refactor CHS guessing to be usable outside of IDE
Date: Wed, 05 Dec 2007 10:24:42 -0600 [thread overview]
Message-ID: <4756D0CA.3030105@us.ibm.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 151 bytes --]
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
[-- Attachment #2: bdrv-guess-geometry.diff --]
[-- Type: text/x-patch, Size: 10050 bytes --]
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);
reply other threads:[~2007-12-05 16:24 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4756D0CA.3030105@us.ibm.com \
--to=aliguori@us.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.