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,6 +739,122 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
739 *nb_sectors_ptr = length; 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 void bdrv_set_geometry_hint(BlockDriverState *bs, 858 void bdrv_set_geometry_hint(BlockDriverState *bs,
743 int cyls, int heads, int secs) 859 int cyls, int heads, int secs)
744 { 860 {
@@ -78,6 +78,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset, @@ -78,6 +78,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
78 int bdrv_truncate(BlockDriverState *bs, int64_t offset); 78 int bdrv_truncate(BlockDriverState *bs, int64_t offset);
79 int64_t bdrv_getlength(BlockDriverState *bs); 79 int64_t bdrv_getlength(BlockDriverState *bs);
80 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); 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 int bdrv_commit(BlockDriverState *bs); 82 int bdrv_commit(BlockDriverState *bs);
82 /* async block I/O */ 83 /* async block I/O */
83 typedef struct BlockDriverAIOCB BlockDriverAIOCB; 84 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
hw/ide.c
@@ -2676,69 +2676,13 @@ static void ide_reset(IDEState *s) @@ -2676,69 +2676,13 @@ static void ide_reset(IDEState *s)
2676 s->media_changed = 0; 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 static void ide_init2(IDEState *ide_state, 2679 static void ide_init2(IDEState *ide_state,
2736 BlockDriverState *hd0, BlockDriverState *hd1, 2680 BlockDriverState *hd0, BlockDriverState *hd1,
2737 qemu_irq irq) 2681 qemu_irq irq)
2738 { 2682 {
2739 IDEState *s; 2683 IDEState *s;
2740 static int drive_serial = 1; 2684 static int drive_serial = 1;
2741 - int i, cylinders, heads, secs, translation, lba_detected = 0; 2685 + int i, cylinders, heads, secs;
2742 uint64_t nb_sectors; 2686 uint64_t nb_sectors;
2743 2687
2744 for(i = 0; i < 2; i++) { 2688 for(i = 0; i < 2; i++) {
@@ -2750,56 +2694,12 @@ static void ide_init2(IDEState *ide_state, @@ -2750,56 +2694,12 @@ static void ide_init2(IDEState *ide_state,
2750 s->bs = hd1; 2694 s->bs = hd1;
2751 if (s->bs) { 2695 if (s->bs) {
2752 bdrv_get_geometry(s->bs, &nb_sectors); 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 s->nb_sectors = nb_sectors; 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 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { 2703 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
2804 s->is_cdrom = 1; 2704 s->is_cdrom = 1;
2805 bdrv_set_change_cb(s->bs, cdrom_change_cb, s); 2705 bdrv_set_change_cb(s->bs, cdrom_change_cb, s);