?? mc146818rtc.c
字號:
static void rtc_update_second2(void *opaque){ RTCState *s = opaque; if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { rtc_copy_date(s); } /* check alarm */ if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) && ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) && ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) { s->cmos_data[RTC_REG_C] |= 0xa0; qemu_irq_raise(s->irq); } } /* update ended interrupt */ if (s->cmos_data[RTC_REG_B] & REG_B_UIE) { s->cmos_data[RTC_REG_C] |= 0x90; qemu_irq_raise(s->irq); } /* clear update in progress bit */ s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; s->next_second_time += ticks_per_sec; qemu_mod_timer(s->second_timer, s->next_second_time);}static uint32_t cmos_ioport_read(void *opaque, uint32_t addr){ RTCState *s = opaque; int ret; if ((addr & 1) == 0) { return 0xff; } else { switch(s->cmos_index) { case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: case RTC_DAY_OF_WEEK: case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_A: ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_C: ret = s->cmos_data[s->cmos_index]; qemu_irq_lower(s->irq); s->cmos_data[RTC_REG_C] = 0x00; break; default: ret = s->cmos_data[s->cmos_index]; break; }#ifdef DEBUG_CMOS printf("cmos: read index=0x%02x val=0x%02x\n", s->cmos_index, ret);#endif return ret; }}void rtc_set_memory(RTCState *s, int addr, int val){ if (addr >= 0 && addr <= 127) s->cmos_data[addr] = val;}void rtc_set_date(RTCState *s, const struct tm *tm){ s->current_tm = *tm; rtc_copy_date(s);}/* PC cmos mappings */#define REG_IBM_CENTURY_BYTE 0x32#define REG_IBM_PS2_CENTURY_BYTE 0x37static void rtc_set_date_from_host(RTCState *s){ time_t ti; struct tm *tm; int val; /* set the CMOS date */ if (rtc_start_date == -1) { time(&ti); if (rtc_utc) tm = gmtime(&ti); else tm = localtime(&ti); } else { ti = rtc_start_date; tm = gmtime(&ti); } rtc_set_date(s, tm); val = to_bcd(s, (tm->tm_year / 100) + 19); rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val); rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);}static void rtc_save(QEMUFile *f, void *opaque){ RTCState *s = opaque; qemu_put_buffer(f, s->cmos_data, 128); qemu_put_8s(f, &s->cmos_index); qemu_put_be32(f, s->current_tm.tm_sec); qemu_put_be32(f, s->current_tm.tm_min); qemu_put_be32(f, s->current_tm.tm_hour); qemu_put_be32(f, s->current_tm.tm_wday); qemu_put_be32(f, s->current_tm.tm_mday); qemu_put_be32(f, s->current_tm.tm_mon); qemu_put_be32(f, s->current_tm.tm_year); qemu_put_timer(f, s->periodic_timer); qemu_put_be64(f, s->next_periodic_time); qemu_put_be64(f, s->next_second_time); qemu_put_timer(f, s->second_timer); qemu_put_timer(f, s->second_timer2);}static int rtc_load(QEMUFile *f, void *opaque, int version_id){ RTCState *s = opaque; if (version_id != 1) return -EINVAL; qemu_get_buffer(f, s->cmos_data, 128); qemu_get_8s(f, &s->cmos_index); s->current_tm.tm_sec=qemu_get_be32(f); s->current_tm.tm_min=qemu_get_be32(f); s->current_tm.tm_hour=qemu_get_be32(f); s->current_tm.tm_wday=qemu_get_be32(f); s->current_tm.tm_mday=qemu_get_be32(f); s->current_tm.tm_mon=qemu_get_be32(f); s->current_tm.tm_year=qemu_get_be32(f); qemu_get_timer(f, s->periodic_timer); s->next_periodic_time=qemu_get_be64(f); s->next_second_time=qemu_get_be64(f); qemu_get_timer(f, s->second_timer); qemu_get_timer(f, s->second_timer2); return 0;}RTCState *rtc_init(int base, qemu_irq irq){ RTCState *s; s = qemu_mallocz(sizeof(RTCState)); if (!s) return NULL; s->irq = irq; s->cmos_data[RTC_REG_A] = 0x26; s->cmos_data[RTC_REG_B] = 0x02; s->cmos_data[RTC_REG_C] = 0x00; s->cmos_data[RTC_REG_D] = 0x80; rtc_set_date_from_host(s); s->periodic_timer = qemu_new_timer(vm_clock, rtc_periodic_timer, s); s->second_timer = qemu_new_timer(vm_clock, rtc_update_second, s); s->second_timer2 = qemu_new_timer(vm_clock, rtc_update_second2, s); s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100; qemu_mod_timer(s->second_timer2, s->next_second_time); register_ioport_write(base, 2, 1, cmos_ioport_write, s); register_ioport_read(base, 2, 1, cmos_ioport_read, s); register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); return s;}/* Memory mapped interface */static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr){ RTCState *s = opaque; return cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;}static void cmos_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value){ RTCState *s = opaque; cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);}static uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr){ RTCState *s = opaque; uint32_t val; val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;#ifdef TARGET_WORDS_BIGENDIAN val = bswap16(val);#endif return val;}static void cmos_mm_writew (void *opaque, target_phys_addr_t addr, uint32_t value){ RTCState *s = opaque;#ifdef TARGET_WORDS_BIGENDIAN value = bswap16(value);#endif cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);}static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr){ RTCState *s = opaque; uint32_t val; val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift);#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif return val;}static void cmos_mm_writel (void *opaque, target_phys_addr_t addr, uint32_t value){ RTCState *s = opaque;#ifdef TARGET_WORDS_BIGENDIAN value = bswap32(value);#endif cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value);}static CPUReadMemoryFunc *rtc_mm_read[] = { &cmos_mm_readb, &cmos_mm_readw, &cmos_mm_readl,};static CPUWriteMemoryFunc *rtc_mm_write[] = { &cmos_mm_writeb, &cmos_mm_writew, &cmos_mm_writel,};RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq){ RTCState *s; int io_memory; s = qemu_mallocz(sizeof(RTCState)); if (!s) return NULL; s->irq = irq; s->cmos_data[RTC_REG_A] = 0x26; s->cmos_data[RTC_REG_B] = 0x02; s->cmos_data[RTC_REG_C] = 0x00; s->cmos_data[RTC_REG_D] = 0x80; s->base = base; rtc_set_date_from_host(s); s->periodic_timer = qemu_new_timer(vm_clock, rtc_periodic_timer, s); s->second_timer = qemu_new_timer(vm_clock, rtc_update_second, s); s->second_timer2 = qemu_new_timer(vm_clock, rtc_update_second2, s); s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100; qemu_mod_timer(s->second_timer2, s->next_second_time); io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s); cpu_register_physical_memory(base, 2 << it_shift, io_memory); register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); return s;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -