aboutsummaryrefslogtreecommitdiffstats
path: root/hw/goldfish_timer.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:35 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:35 -0800
commitf721e3ac031f892af46f255a47d7f54a91317b30 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /hw/goldfish_timer.c
parentbae1bc39312d5019bd9a5b8d840a529213a69a17 (diff)
downloadexternal_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.zip
external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.gz
external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'hw/goldfish_timer.c')
-rw-r--r--hw/goldfish_timer.c256
1 files changed, 0 insertions, 256 deletions
diff --git a/hw/goldfish_timer.c b/hw/goldfish_timer.c
deleted file mode 100644
index 73f1455..0000000
--- a/hw/goldfish_timer.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "qemu-timer.h"
-#include "cpu.h"
-#include "arm_pic.h"
-#include "goldfish_device.h"
-
-enum {
- TIMER_TIME_LOW = 0x00, // get low bits of current time and update TIMER_TIME_HIGH
- TIMER_TIME_HIGH = 0x04, // get high bits of time at last TIMER_TIME_LOW read
- TIMER_ALARM_LOW = 0x08, // set low bits of alarm and activate it
- TIMER_ALARM_HIGH = 0x0c, // set high bits of next alarm
- TIMER_CLEAR_INTERRUPT = 0x10,
- TIMER_CLEAR_ALARM = 0x14
-};
-
-struct timer_state {
- struct goldfish_device dev;
- uint32_t alarm_low;
- int32_t alarm_high;
- int64_t now;
- int armed;
- QEMUTimer *timer;
-};
-
-#define GOLDFISH_TIMER_SAVE_VERSION 1
-
-static void goldfish_timer_save(QEMUFile* f, void* opaque)
-{
- struct timer_state* s = opaque;
-
- qemu_put_be64(f, s->now); /* in case the kernel is in the middle of a timer read */
- qemu_put_byte(f, s->armed);
- if (s->armed) {
- int64_t now = qemu_get_clock(vm_clock);
- int64_t alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000);
- qemu_put_be64(f, alarm-now);
- }
-}
-
-static int goldfish_timer_load(QEMUFile* f, void* opaque, int version_id)
-{
- struct timer_state* s = opaque;
-
- if (version_id != GOLDFISH_TIMER_SAVE_VERSION)
- return -1;
-
- s->now = qemu_get_be64(f);
- s->armed = qemu_get_byte(f);
- if (s->armed) {
- int64_t now = qemu_get_clock(vm_clock);
- int64_t diff = qemu_get_be64(f);
- int64_t alarm = now + diff;
-
- if (alarm <= now) {
- goldfish_device_set_irq(&s->dev, 0, 1);
- s->armed = 0;
- } else {
- qemu_mod_timer(s->timer, alarm);
- }
- }
- return 0;
-}
-
-static uint32_t goldfish_timer_read(void *opaque, target_phys_addr_t offset)
-{
- struct timer_state *s = (struct timer_state *)opaque;
- offset -= s->dev.base;
- switch(offset) {
- case TIMER_TIME_LOW:
- s->now = muldiv64(qemu_get_clock(vm_clock), 1000000000, ticks_per_sec);
- return s->now;
- case TIMER_TIME_HIGH:
- return s->now >> 32;
- default:
- cpu_abort (cpu_single_env, "goldfish_timer_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value)
-{
- struct timer_state *s = (struct timer_state *)opaque;
- int64_t alarm, now;
- offset -= s->dev.base;
- switch(offset) {
- case TIMER_ALARM_LOW:
- s->alarm_low = value;
- alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000);
- now = qemu_get_clock(vm_clock);
- if (alarm <= now) {
- goldfish_device_set_irq(&s->dev, 0, 1);
- } else {
- qemu_mod_timer(s->timer, alarm);
- s->armed = 1;
- }
- break;
- case TIMER_ALARM_HIGH:
- s->alarm_high = value;
- //printf("alarm_high %d\n", s->alarm_high);
- break;
- case TIMER_CLEAR_ALARM:
- qemu_del_timer(s->timer);
- s->armed = 0;
- /* fall through */
- case TIMER_CLEAR_INTERRUPT:
- goldfish_device_set_irq(&s->dev, 0, 0);
- break;
- default:
- cpu_abort (cpu_single_env, "goldfish_timer_write: Bad offset %x\n", offset);
- }
-}
-
-static void goldfish_timer_tick(void *opaque)
-{
- struct timer_state *s = (struct timer_state *)opaque;
-
- s->armed = 0;
- goldfish_device_set_irq(&s->dev, 0, 1);
-}
-
-struct rtc_state {
- struct goldfish_device dev;
- uint32_t alarm_low;
- int32_t alarm_high;
- int64_t now;
-};
-
-/* we save the RTC for the case where the kernel is in the middle of a rtc_read
- * (i.e. it has read the low 32-bit of s->now, but not the high 32-bits yet */
-#define GOLDFISH_RTC_SAVE_VERSION 1
-
-static void goldfish_rtc_save(QEMUFile* f, void* opaque)
-{
- struct rtc_state* s = opaque;
-
- qemu_put_be64(f, s->now);
-}
-
-static int goldfish_rtc_load(QEMUFile* f, void* opaque, int version_id)
-{
- struct rtc_state* s = opaque;
-
- if (version_id != GOLDFISH_RTC_SAVE_VERSION)
- return -1;
-
- /* this is an old value that is not correct. but that's ok anyway */
- s->now = qemu_get_be64(f);
- return 0;
-}
-
-static uint32_t goldfish_rtc_read(void *opaque, target_phys_addr_t offset)
-{
- struct rtc_state *s = (struct rtc_state *)opaque;
- offset -= s->dev.base;
- switch(offset) {
- case 0x0:
- s->now = (int64_t)time(NULL) * 1000000000;
- return s->now;
- case 0x4:
- return s->now >> 32;
- default:
- cpu_abort (cpu_single_env, "goldfish_rtc_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void goldfish_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value)
-{
- struct rtc_state *s = (struct rtc_state *)opaque;
- int64_t alarm;
- offset -= s->dev.base;
- switch(offset) {
- case 0x8:
- s->alarm_low = value;
- alarm = s->alarm_low | (int64_t)s->alarm_high << 32;
- //printf("next alarm at %lld, tps %lld\n", alarm, ticks_per_sec);
- //qemu_mod_timer(s->timer, alarm);
- break;
- case 0xc:
- s->alarm_high = value;
- //printf("alarm_high %d\n", s->alarm_high);
- break;
- case 0x10:
- goldfish_device_set_irq(&s->dev, 0, 0);
- break;
- default:
- cpu_abort (cpu_single_env, "goldfish_rtc_write: Bad offset %x\n", offset);
- }
-}
-
-static struct timer_state timer_state = {
- .dev = {
- .name = "goldfish_timer",
- .id = -1,
- .size = 0x1000,
- .irq_count = 1,
- }
-};
-
-static struct timer_state rtc_state = {
- .dev = {
- .name = "goldfish_rtc",
- .id = -1,
- .size = 0x1000,
- .irq_count = 1,
- }
-};
-
-static CPUReadMemoryFunc *goldfish_timer_readfn[] = {
- goldfish_timer_read,
- goldfish_timer_read,
- goldfish_timer_read
-};
-
-static CPUWriteMemoryFunc *goldfish_timer_writefn[] = {
- goldfish_timer_write,
- goldfish_timer_write,
- goldfish_timer_write
-};
-
-static CPUReadMemoryFunc *goldfish_rtc_readfn[] = {
- goldfish_rtc_read,
- goldfish_rtc_read,
- goldfish_rtc_read
-};
-
-static CPUWriteMemoryFunc *goldfish_rtc_writefn[] = {
- goldfish_rtc_write,
- goldfish_rtc_write,
- goldfish_rtc_write
-};
-
-void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq)
-{
- timer_state.dev.base = timerbase;
- timer_state.dev.irq = timerirq;
- timer_state.timer = qemu_new_timer(vm_clock, goldfish_timer_tick, &timer_state);
- goldfish_device_add(&timer_state.dev, goldfish_timer_readfn, goldfish_timer_writefn, &timer_state);
- register_savevm( "goldfish_timer", 0, GOLDFISH_TIMER_SAVE_VERSION,
- goldfish_timer_save, goldfish_timer_load, &timer_state);
-
- goldfish_device_add(&rtc_state.dev, goldfish_rtc_readfn, goldfish_rtc_writefn, &rtc_state);
- register_savevm( "goldfish_rtc", 0, GOLDFISH_RTC_SAVE_VERSION,
- goldfish_rtc_save, goldfish_rtc_load, &rtc_state);
-}
-