Commit 46d4767d93bcb2e84869ba6d2344ebff4382be86

Authored by bellard
1 parent e35c55fe

better BIOS ATA translation support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1153 c046a42c-6fe2-441c-8c8c-71466251a162
@@ -348,6 +348,11 @@ void bdrv_set_type_hint(BlockDriverState *bs, int type) @@ -348,6 +348,11 @@ void bdrv_set_type_hint(BlockDriverState *bs, int type)
348 type == BDRV_TYPE_FLOPPY)); 348 type == BDRV_TYPE_FLOPPY));
349 } 349 }
350 350
  351 +void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
  352 +{
  353 + bs->translation = translation;
  354 +}
  355 +
351 void bdrv_get_geometry_hint(BlockDriverState *bs, 356 void bdrv_get_geometry_hint(BlockDriverState *bs,
352 int *pcyls, int *pheads, int *psecs) 357 int *pcyls, int *pheads, int *psecs)
353 { 358 {
@@ -361,6 +366,11 @@ int bdrv_get_type_hint(BlockDriverState *bs) @@ -361,6 +366,11 @@ int bdrv_get_type_hint(BlockDriverState *bs)
361 return bs->type; 366 return bs->type;
362 } 367 }
363 368
  369 +int bdrv_get_translation_hint(BlockDriverState *bs)
  370 +{
  371 + return bs->translation;
  372 +}
  373 +
364 int bdrv_is_removable(BlockDriverState *bs) 374 int bdrv_is_removable(BlockDriverState *bs)
365 { 375 {
366 return bs->removable; 376 return bs->removable;
block_int.h
@@ -68,7 +68,7 @@ struct BlockDriverState { @@ -68,7 +68,7 @@ struct BlockDriverState {
68 68
69 /* NOTE: the following infos are only hints for real hardware 69 /* NOTE: the following infos are only hints for real hardware
70 drivers. They are not used by the block driver */ 70 drivers. They are not used by the block driver */
71 - int cyls, heads, secs; 71 + int cyls, heads, secs, translation;
72 int type; 72 int type;
73 char device_name[32]; 73 char device_name[32];
74 BlockDriverState *next; 74 BlockDriverState *next;
hw/ide.c
@@ -1826,11 +1826,11 @@ struct partition { @@ -1826,11 +1826,11 @@ struct partition {
1826 uint32_t nr_sects; /* nr of sectors in partition */ 1826 uint32_t nr_sects; /* nr of sectors in partition */
1827 } __attribute__((packed)); 1827 } __attribute__((packed));
1828 1828
1829 -/* try to guess the IDE geometry from the MSDOS partition table */ 1829 +/* try to guess the IDE physical geometry from the MSDOS partition table */
1830 static void ide_guess_geometry(IDEState *s) 1830 static void ide_guess_geometry(IDEState *s)
1831 { 1831 {
1832 uint8_t buf[512]; 1832 uint8_t buf[512];
1833 - int ret, i; 1833 + int ret, i, heads, sectors, cylinders;
1834 struct partition *p; 1834 struct partition *p;
1835 uint32_t nr_sects; 1835 uint32_t nr_sects;
1836 1836
@@ -1848,9 +1848,18 @@ static void ide_guess_geometry(IDEState *s) @@ -1848,9 +1848,18 @@ static void ide_guess_geometry(IDEState *s)
1848 if (nr_sects && p->end_head) { 1848 if (nr_sects && p->end_head) {
1849 /* We make the assumption that the partition terminates on 1849 /* We make the assumption that the partition terminates on
1850 a cylinder boundary */ 1850 a cylinder boundary */
1851 - s->heads = p->end_head + 1;  
1852 - s->sectors = p->end_sector & 63;  
1853 - s->cylinders = s->nb_sectors / (s->heads * s->sectors); 1851 + heads = p->end_head + 1;
  1852 + if (heads < 1 || heads > 16)
  1853 + continue;
  1854 + sectors = p->end_sector & 63;
  1855 + if (sectors == 0)
  1856 + continue;
  1857 + cylinders = s->nb_sectors / (heads * sectors);
  1858 + if (cylinders < 1 || cylinders > 16383)
  1859 + continue;
  1860 + s->heads = heads;
  1861 + s->sectors = sectors;
  1862 + s->cylinders = cylinders;
1854 #if 0 1863 #if 0
1855 printf("guessed partition: CHS=%d %d %d\n", 1864 printf("guessed partition: CHS=%d %d %d\n",
1856 s->cylinders, s->heads, s->sectors); 1865 s->cylinders, s->heads, s->sectors);
@@ -1885,7 +1894,7 @@ static void ide_init2(IDEState *ide_state, int irq, @@ -1885,7 +1894,7 @@ static void ide_init2(IDEState *ide_state, int irq,
1885 } else { 1894 } else {
1886 ide_guess_geometry(s); 1895 ide_guess_geometry(s);
1887 if (s->cylinders == 0) { 1896 if (s->cylinders == 0) {
1888 - /* if no geometry, use a LBA compatible one */ 1897 + /* if no geometry, use a standard physical disk geometry */
1889 cylinders = nb_sectors / (16 * 63); 1898 cylinders = nb_sectors / (16 * 63);
1890 if (cylinders > 16383) 1899 if (cylinders > 16383)
1891 cylinders = 16383; 1900 cylinders = 16383;
@@ -217,19 +217,23 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table @@ -217,19 +217,23 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
217 val = 0; 217 val = 0;
218 for (i = 0; i < 4; i++) { 218 for (i = 0; i < 4; i++) {
219 if (hd_table[i]) { 219 if (hd_table[i]) {
220 - int cylinders, heads, sectors;  
221 - uint8_t translation;  
222 - /* NOTE: bdrv_get_geometry_hint() returns the geometry  
223 - that the hard disk returns. It is always such that: 1 <=  
224 - sects <= 63, 1 <= heads <= 16, 1 <= cylinders <=  
225 - 16383. The BIOS geometry can be different. */  
226 - bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);  
227 - if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {  
228 - /* No translation. */  
229 - translation = 0; 220 + int cylinders, heads, sectors, translation;
  221 + /* NOTE: bdrv_get_geometry_hint() returns the physical
  222 + geometry. It is always such that: 1 <= sects <= 63, 1
  223 + <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
  224 + geometry can be different if a translation is done. */
  225 + translation = bdrv_get_translation_hint(hd_table[i]);
  226 + if (translation == BIOS_ATA_TRANSLATION_AUTO) {
  227 + bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
  228 + if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
  229 + /* No translation. */
  230 + translation = 0;
  231 + } else {
  232 + /* LBA translation. */
  233 + translation = 1;
  234 + }
230 } else { 235 } else {
231 - /* LBA translation. */  
232 - translation = 1; 236 + translation--;
233 } 237 }
234 val |= translation << (i * 2); 238 val |= translation << (i * 2);
235 } 239 }
qemu-doc.texi
@@ -343,6 +343,12 @@ Change gdb connection port. @@ -343,6 +343,12 @@ Change gdb connection port.
343 Do not start CPU at startup (you must type 'c' in the monitor). 343 Do not start CPU at startup (you must type 'c' in the monitor).
344 @item -d 344 @item -d
345 Output log in /tmp/qemu.log 345 Output log in /tmp/qemu.log
  346 +@item -hdachs c,h,s,[,t]
  347 +Force hard disk 0 physical geometry (1 <= @var{c} <= 16383, 1 <=
  348 +@var{h} <= 16, 1 <= @var{s} <= 63) and optionally force the BIOS
  349 +translation mode (@var{t}=none, lba or auto). Usually QEMU can guess
  350 +all thoses parameters. This option is useful for old MS-DOS disk
  351 +images.
346 @item -isa 352 @item -isa
347 Simulate an ISA-only system (default is PCI system). 353 Simulate an ISA-only system (default is PCI system).
348 @item -std-vga 354 @item -std-vga
@@ -2537,7 +2537,8 @@ void help(void) @@ -2537,7 +2537,8 @@ void help(void)
2537 "-s wait gdb connection to port %d\n" 2537 "-s wait gdb connection to port %d\n"
2538 "-p port change gdb connection port\n" 2538 "-p port change gdb connection port\n"
2539 "-d item1,... output log to %s (use -d ? for a list of log items)\n" 2539 "-d item1,... output log to %s (use -d ? for a list of log items)\n"
2540 - "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" 2540 + "-hdachs c,h,s[,t] force hard disk 0 physical geometry and the optional BIOS\n"
  2541 + " translation (t=none or lba) (usually qemu can guess them)\n"
2541 "-L path set the directory for the BIOS and VGA BIOS\n" 2542 "-L path set the directory for the BIOS and VGA BIOS\n"
2542 #ifdef USE_CODE_COPY 2543 #ifdef USE_CODE_COPY
2543 "-no-code-copy disable code copy acceleration\n" 2544 "-no-code-copy disable code copy acceleration\n"
@@ -2753,7 +2754,7 @@ int main(int argc, char **argv) @@ -2753,7 +2754,7 @@ int main(int argc, char **argv)
2753 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; 2754 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
2754 const char *kernel_filename, *kernel_cmdline; 2755 const char *kernel_filename, *kernel_cmdline;
2755 DisplayState *ds = &display_state; 2756 DisplayState *ds = &display_state;
2756 - int cyls, heads, secs; 2757 + int cyls, heads, secs, translation;
2757 int start_emulation = 1; 2758 int start_emulation = 1;
2758 uint8_t macaddr[6]; 2759 uint8_t macaddr[6];
2759 int net_if_type, nb_tun_fds, tun_fds[MAX_NICS]; 2760 int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
@@ -2788,6 +2789,7 @@ int main(int argc, char **argv) @@ -2788,6 +2789,7 @@ int main(int argc, char **argv)
2788 kernel_cmdline = ""; 2789 kernel_cmdline = "";
2789 has_cdrom = 1; 2790 has_cdrom = 1;
2790 cyls = heads = secs = 0; 2791 cyls = heads = secs = 0;
  2792 + translation = BIOS_ATA_TRANSLATION_AUTO;
2791 pstrcpy(monitor_device, sizeof(monitor_device), "vc"); 2793 pstrcpy(monitor_device, sizeof(monitor_device), "vc");
2792 2794
2793 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc"); 2795 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc");
@@ -2857,17 +2859,34 @@ int main(int argc, char **argv) @@ -2857,17 +2859,34 @@ int main(int argc, char **argv)
2857 const char *p; 2859 const char *p;
2858 p = optarg; 2860 p = optarg;
2859 cyls = strtol(p, (char **)&p, 0); 2861 cyls = strtol(p, (char **)&p, 0);
  2862 + if (cyls < 1 || cyls > 16383)
  2863 + goto chs_fail;
2860 if (*p != ',') 2864 if (*p != ',')
2861 goto chs_fail; 2865 goto chs_fail;
2862 p++; 2866 p++;
2863 heads = strtol(p, (char **)&p, 0); 2867 heads = strtol(p, (char **)&p, 0);
  2868 + if (heads < 1 || heads > 16)
  2869 + goto chs_fail;
2864 if (*p != ',') 2870 if (*p != ',')
2865 goto chs_fail; 2871 goto chs_fail;
2866 p++; 2872 p++;
2867 secs = strtol(p, (char **)&p, 0); 2873 secs = strtol(p, (char **)&p, 0);
2868 - if (*p != '\0') { 2874 + if (secs < 1 || secs > 63)
  2875 + goto chs_fail;
  2876 + if (*p == ',') {
  2877 + p++;
  2878 + if (!strcmp(p, "none"))
  2879 + translation = BIOS_ATA_TRANSLATION_NONE;
  2880 + else if (!strcmp(p, "lba"))
  2881 + translation = BIOS_ATA_TRANSLATION_LBA;
  2882 + else if (!strcmp(p, "auto"))
  2883 + translation = BIOS_ATA_TRANSLATION_AUTO;
  2884 + else
  2885 + goto chs_fail;
  2886 + } else if (*p != '\0') {
2869 chs_fail: 2887 chs_fail:
2870 - cyls = 0; 2888 + fprintf(stderr, "qemu: invalid physical CHS format\n");
  2889 + exit(1);
2871 } 2890 }
2872 } 2891 }
2873 break; 2892 break;
@@ -3230,8 +3249,10 @@ int main(int argc, char **argv) @@ -3230,8 +3249,10 @@ int main(int argc, char **argv)
3230 hd_filename[i]); 3249 hd_filename[i]);
3231 exit(1); 3250 exit(1);
3232 } 3251 }
3233 - if (i == 0 && cyls != 0) 3252 + if (i == 0 && cyls != 0) {
3234 bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs); 3253 bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
  3254 + bdrv_set_translation_hint(bs_table[i], translation);
  3255 + }
3235 } 3256 }
3236 } 3257 }
3237 3258
@@ -383,13 +383,18 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); @@ -383,13 +383,18 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
383 #define BDRV_TYPE_HD 0 383 #define BDRV_TYPE_HD 0
384 #define BDRV_TYPE_CDROM 1 384 #define BDRV_TYPE_CDROM 1
385 #define BDRV_TYPE_FLOPPY 2 385 #define BDRV_TYPE_FLOPPY 2
  386 +#define BIOS_ATA_TRANSLATION_AUTO 0
  387 +#define BIOS_ATA_TRANSLATION_NONE 1
  388 +#define BIOS_ATA_TRANSLATION_LBA 2
386 389
387 void bdrv_set_geometry_hint(BlockDriverState *bs, 390 void bdrv_set_geometry_hint(BlockDriverState *bs,
388 int cyls, int heads, int secs); 391 int cyls, int heads, int secs);
389 void bdrv_set_type_hint(BlockDriverState *bs, int type); 392 void bdrv_set_type_hint(BlockDriverState *bs, int type);
  393 +void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
390 void bdrv_get_geometry_hint(BlockDriverState *bs, 394 void bdrv_get_geometry_hint(BlockDriverState *bs,
391 int *pcyls, int *pheads, int *psecs); 395 int *pcyls, int *pheads, int *psecs);
392 int bdrv_get_type_hint(BlockDriverState *bs); 396 int bdrv_get_type_hint(BlockDriverState *bs);
  397 +int bdrv_get_translation_hint(BlockDriverState *bs);
393 int bdrv_is_removable(BlockDriverState *bs); 398 int bdrv_is_removable(BlockDriverState *bs);
394 int bdrv_is_read_only(BlockDriverState *bs); 399 int bdrv_is_read_only(BlockDriverState *bs);
395 int bdrv_is_inserted(BlockDriverState *bs); 400 int bdrv_is_inserted(BlockDriverState *bs);