Commit f3d54fc4948b5525cc15e2a082f0cec8610ec5b4

Authored by aliguori
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
... ... @@ -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 {
... ...
... ... @@ -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);
... ...