Refactor CHS guessing to be usable outside of IDE
PATCH 1/2 Refactor CHS guessing to be usable outside of IDE
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
block.c +116 -0
@@ -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) {
block.h +1 -0
@@ -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 */
hw/ide.c +6 -104
129 lines not on this page · raw message