Commit f3d54fc4948b5525cc15e2a082f0cec8610ec5b4
1 parent
357c692c
Abstract out geometry detection code from IDE for reuse
Virtio will want to use the geometry detection code. It doesn't belong in ide.c anyway. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5797 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
123 additions
and
106 deletions
block.c
... | ... | @@ -739,6 +739,122 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr) |
739 | 739 | *nb_sectors_ptr = length; |
740 | 740 | } |
741 | 741 | |
742 | +struct partition { | |
743 | + uint8_t boot_ind; /* 0x80 - active */ | |
744 | + uint8_t head; /* starting head */ | |
745 | + uint8_t sector; /* starting sector */ | |
746 | + uint8_t cyl; /* starting cylinder */ | |
747 | + uint8_t sys_ind; /* What partition type */ | |
748 | + uint8_t end_head; /* end head */ | |
749 | + uint8_t end_sector; /* end sector */ | |
750 | + uint8_t end_cyl; /* end cylinder */ | |
751 | + uint32_t start_sect; /* starting sector counting from 0 */ | |
752 | + uint32_t nr_sects; /* nr of sectors in partition */ | |
753 | +} __attribute__((packed)); | |
754 | + | |
755 | +/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ | |
756 | +static int guess_disk_lchs(BlockDriverState *bs, | |
757 | + int *pcylinders, int *pheads, int *psectors) | |
758 | +{ | |
759 | + uint8_t buf[512]; | |
760 | + int ret, i, heads, sectors, cylinders; | |
761 | + struct partition *p; | |
762 | + uint32_t nr_sects; | |
763 | + int64_t nb_sectors; | |
764 | + | |
765 | + bdrv_get_geometry(bs, &nb_sectors); | |
766 | + | |
767 | + ret = bdrv_read(bs, 0, buf, 1); | |
768 | + if (ret < 0) | |
769 | + return -1; | |
770 | + /* test msdos magic */ | |
771 | + if (buf[510] != 0x55 || buf[511] != 0xaa) | |
772 | + return -1; | |
773 | + for(i = 0; i < 4; i++) { | |
774 | + p = ((struct partition *)(buf + 0x1be)) + i; | |
775 | + nr_sects = le32_to_cpu(p->nr_sects); | |
776 | + if (nr_sects && p->end_head) { | |
777 | + /* We make the assumption that the partition terminates on | |
778 | + a cylinder boundary */ | |
779 | + heads = p->end_head + 1; | |
780 | + sectors = p->end_sector & 63; | |
781 | + if (sectors == 0) | |
782 | + continue; | |
783 | + cylinders = nb_sectors / (heads * sectors); | |
784 | + if (cylinders < 1 || cylinders > 16383) | |
785 | + continue; | |
786 | + *pheads = heads; | |
787 | + *psectors = sectors; | |
788 | + *pcylinders = cylinders; | |
789 | +#if 0 | |
790 | + printf("guessed geometry: LCHS=%d %d %d\n", | |
791 | + cylinders, heads, sectors); | |
792 | +#endif | |
793 | + return 0; | |
794 | + } | |
795 | + } | |
796 | + return -1; | |
797 | +} | |
798 | + | |
799 | +void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs) | |
800 | +{ | |
801 | + int translation, lba_detected = 0; | |
802 | + int cylinders, heads, secs; | |
803 | + int64_t nb_sectors; | |
804 | + | |
805 | + /* if a geometry hint is available, use it */ | |
806 | + bdrv_get_geometry(bs, &nb_sectors); | |
807 | + bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs); | |
808 | + translation = bdrv_get_translation_hint(bs); | |
809 | + if (cylinders != 0) { | |
810 | + *pcyls = cylinders; | |
811 | + *pheads = heads; | |
812 | + *psecs = secs; | |
813 | + } else { | |
814 | + if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) { | |
815 | + if (heads > 16) { | |
816 | + /* if heads > 16, it means that a BIOS LBA | |
817 | + translation was active, so the default | |
818 | + hardware geometry is OK */ | |
819 | + lba_detected = 1; | |
820 | + goto default_geometry; | |
821 | + } else { | |
822 | + *pcyls = cylinders; | |
823 | + *pheads = heads; | |
824 | + *psecs = secs; | |
825 | + /* disable any translation to be in sync with | |
826 | + the logical geometry */ | |
827 | + if (translation == BIOS_ATA_TRANSLATION_AUTO) { | |
828 | + bdrv_set_translation_hint(bs, | |
829 | + BIOS_ATA_TRANSLATION_NONE); | |
830 | + } | |
831 | + } | |
832 | + } else { | |
833 | + default_geometry: | |
834 | + /* if no geometry, use a standard physical disk geometry */ | |
835 | + cylinders = nb_sectors / (16 * 63); | |
836 | + | |
837 | + if (cylinders > 16383) | |
838 | + cylinders = 16383; | |
839 | + else if (cylinders < 2) | |
840 | + cylinders = 2; | |
841 | + *pcyls = cylinders; | |
842 | + *pheads = 16; | |
843 | + *psecs = 63; | |
844 | + if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) { | |
845 | + if ((*pcyls * *pheads) <= 131072) { | |
846 | + bdrv_set_translation_hint(bs, | |
847 | + BIOS_ATA_TRANSLATION_LARGE); | |
848 | + } else { | |
849 | + bdrv_set_translation_hint(bs, | |
850 | + BIOS_ATA_TRANSLATION_LBA); | |
851 | + } | |
852 | + } | |
853 | + } | |
854 | + bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs); | |
855 | + } | |
856 | +} | |
857 | + | |
742 | 858 | void bdrv_set_geometry_hint(BlockDriverState *bs, |
743 | 859 | int cyls, int heads, int secs) |
744 | 860 | { | ... | ... |
block.h
... | ... | @@ -78,6 +78,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset, |
78 | 78 | int bdrv_truncate(BlockDriverState *bs, int64_t offset); |
79 | 79 | int64_t bdrv_getlength(BlockDriverState *bs); |
80 | 80 | void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); |
81 | +void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs); | |
81 | 82 | int bdrv_commit(BlockDriverState *bs); |
82 | 83 | /* async block I/O */ |
83 | 84 | typedef struct BlockDriverAIOCB BlockDriverAIOCB; | ... | ... |
hw/ide.c
... | ... | @@ -2676,69 +2676,13 @@ static void ide_reset(IDEState *s) |
2676 | 2676 | s->media_changed = 0; |
2677 | 2677 | } |
2678 | 2678 | |
2679 | -struct partition { | |
2680 | - uint8_t boot_ind; /* 0x80 - active */ | |
2681 | - uint8_t head; /* starting head */ | |
2682 | - uint8_t sector; /* starting sector */ | |
2683 | - uint8_t cyl; /* starting cylinder */ | |
2684 | - uint8_t sys_ind; /* What partition type */ | |
2685 | - uint8_t end_head; /* end head */ | |
2686 | - uint8_t end_sector; /* end sector */ | |
2687 | - uint8_t end_cyl; /* end cylinder */ | |
2688 | - uint32_t start_sect; /* starting sector counting from 0 */ | |
2689 | - uint32_t nr_sects; /* nr of sectors in partition */ | |
2690 | -} __attribute__((packed)); | |
2691 | - | |
2692 | -/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ | |
2693 | -static int guess_disk_lchs(IDEState *s, | |
2694 | - int *pcylinders, int *pheads, int *psectors) | |
2695 | -{ | |
2696 | - uint8_t *buf = s->io_buffer; | |
2697 | - int ret, i, heads, sectors, cylinders; | |
2698 | - struct partition *p; | |
2699 | - uint32_t nr_sects; | |
2700 | - | |
2701 | - ret = bdrv_read(s->bs, 0, buf, 1); | |
2702 | - if (ret < 0) { | |
2703 | - return -1; | |
2704 | - } | |
2705 | - /* test msdos magic */ | |
2706 | - if (buf[510] != 0x55 || buf[511] != 0xaa) { | |
2707 | - return -1; | |
2708 | - } | |
2709 | - for(i = 0; i < 4; i++) { | |
2710 | - p = ((struct partition *)(buf + 0x1be)) + i; | |
2711 | - nr_sects = le32_to_cpu(p->nr_sects); | |
2712 | - if (nr_sects && p->end_head) { | |
2713 | - /* We make the assumption that the partition terminates on | |
2714 | - a cylinder boundary */ | |
2715 | - heads = p->end_head + 1; | |
2716 | - sectors = p->end_sector & 63; | |
2717 | - if (sectors == 0) | |
2718 | - continue; | |
2719 | - cylinders = s->nb_sectors / (heads * sectors); | |
2720 | - if (cylinders < 1 || cylinders > 16383) | |
2721 | - continue; | |
2722 | - *pheads = heads; | |
2723 | - *psectors = sectors; | |
2724 | - *pcylinders = cylinders; | |
2725 | -#if 0 | |
2726 | - printf("guessed geometry: LCHS=%d %d %d\n", | |
2727 | - cylinders, heads, sectors); | |
2728 | -#endif | |
2729 | - return 0; | |
2730 | - } | |
2731 | - } | |
2732 | - return -1; | |
2733 | -} | |
2734 | - | |
2735 | 2679 | static void ide_init2(IDEState *ide_state, |
2736 | 2680 | BlockDriverState *hd0, BlockDriverState *hd1, |
2737 | 2681 | qemu_irq irq) |
2738 | 2682 | { |
2739 | 2683 | IDEState *s; |
2740 | 2684 | static int drive_serial = 1; |
2741 | - int i, cylinders, heads, secs, translation, lba_detected = 0; | |
2685 | + int i, cylinders, heads, secs; | |
2742 | 2686 | uint64_t nb_sectors; |
2743 | 2687 | |
2744 | 2688 | for(i = 0; i < 2; i++) { |
... | ... | @@ -2750,56 +2694,12 @@ static void ide_init2(IDEState *ide_state, |
2750 | 2694 | s->bs = hd1; |
2751 | 2695 | if (s->bs) { |
2752 | 2696 | bdrv_get_geometry(s->bs, &nb_sectors); |
2697 | + bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); | |
2698 | + s->cylinders = cylinders; | |
2699 | + s->heads = heads; | |
2700 | + s->sectors = secs; | |
2753 | 2701 | s->nb_sectors = nb_sectors; |
2754 | - /* if a geometry hint is available, use it */ | |
2755 | - bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); | |
2756 | - translation = bdrv_get_translation_hint(s->bs); | |
2757 | - if (cylinders != 0) { | |
2758 | - s->cylinders = cylinders; | |
2759 | - s->heads = heads; | |
2760 | - s->sectors = secs; | |
2761 | - } else { | |
2762 | - if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) { | |
2763 | - if (heads > 16) { | |
2764 | - /* if heads > 16, it means that a BIOS LBA | |
2765 | - translation was active, so the default | |
2766 | - hardware geometry is OK */ | |
2767 | - lba_detected = 1; | |
2768 | - goto default_geometry; | |
2769 | - } else { | |
2770 | - s->cylinders = cylinders; | |
2771 | - s->heads = heads; | |
2772 | - s->sectors = secs; | |
2773 | - /* disable any translation to be in sync with | |
2774 | - the logical geometry */ | |
2775 | - if (translation == BIOS_ATA_TRANSLATION_AUTO) { | |
2776 | - bdrv_set_translation_hint(s->bs, | |
2777 | - BIOS_ATA_TRANSLATION_NONE); | |
2778 | - } | |
2779 | - } | |
2780 | - } else { | |
2781 | - default_geometry: | |
2782 | - /* if no geometry, use a standard physical disk geometry */ | |
2783 | - cylinders = nb_sectors / (16 * 63); | |
2784 | - if (cylinders > 16383) | |
2785 | - cylinders = 16383; | |
2786 | - else if (cylinders < 2) | |
2787 | - cylinders = 2; | |
2788 | - s->cylinders = cylinders; | |
2789 | - s->heads = 16; | |
2790 | - s->sectors = 63; | |
2791 | - if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) { | |
2792 | - if ((s->cylinders * s->heads) <= 131072) { | |
2793 | - bdrv_set_translation_hint(s->bs, | |
2794 | - BIOS_ATA_TRANSLATION_LARGE); | |
2795 | - } else { | |
2796 | - bdrv_set_translation_hint(s->bs, | |
2797 | - BIOS_ATA_TRANSLATION_LBA); | |
2798 | - } | |
2799 | - } | |
2800 | - } | |
2801 | - bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors); | |
2802 | - } | |
2702 | + | |
2803 | 2703 | if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { |
2804 | 2704 | s->is_cdrom = 1; |
2805 | 2705 | bdrv_set_change_cb(s->bs, cdrom_change_cb, s); | ... | ... |