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); | ... | ... |