static void pc_cmos_init_late(void *opaque) { pc_cmos_init_late_arg *arg = opaque; ISADevice *s = arg->rtc_state; int val; BlockDriverState *hd_table[4]; int i; ide_get_bs(hd_table, arg->idebus0); ide_get_bs(hd_table + 2, arg->idebus1); rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0)); if (hd_table[0]) cmos_init_hd(0x19, 0x1b, hd_table[0], s); if (hd_table[1]) cmos_init_hd(0x1a, 0x24, hd_table[1], s); val = 0; for (i = 0; i < 4; i++) { if (hd_table[i]) { int cylinders, heads, sectors, translation; /* NOTE: bdrv_get_geometry_hint() returns the physical geometry. It is always such that: 1 <= sects <= 63, 1 <= heads <= 16, 1 <= cylinders <= 16383. The BIOS geometry can be different if a translation is done. */ translation = bdrv_get_translation_hint(hd_table[i]); if (translation == BIOS_ATA_TRANSLATION_AUTO) { bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors); if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { /* No translation. */ translation = 0; } else { /* LBA translation. */ translation = 1; } } else { translation--; } val |= translation << (i * 2); } } rtc_set_memory(s, 0x39, val); qemu_unregister_reset(pc_cmos_init_late, opaque); }
static void pc_cmos_init_late(void *opaque) { pc_cmos_init_late_arg *arg = opaque; ISADevice *s = arg->rtc_state; int16_t cylinders; int8_t heads, sectors; int val; int i, trans; val = 0; if (ide_get_geometry(arg->idebus[0], 0, &cylinders, &heads, §ors) >= 0) { cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors); val |= 0xf0; } if (ide_get_geometry(arg->idebus[0], 1, &cylinders, &heads, §ors) >= 0) { cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors); val |= 0x0f; } rtc_set_memory(s, 0x12, val); val = 0; for (i = 0; i < 4; i++) { /* NOTE: ide_get_geometry() returns the physical geometry. It is always such that: 1 <= sects <= 63, 1 <= heads <= 16, 1 <= cylinders <= 16383. The BIOS geometry can be different if a translation is done. */ if (ide_get_geometry(arg->idebus[i / 2], i % 2, &cylinders, &heads, §ors) >= 0) { trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1; assert((trans & ~3) == 0); val |= trans << (i * 2); } } rtc_set_memory(s, 0x39, val); qemu_unregister_reset(pc_cmos_init_late, opaque); }