/*
 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
 *
 * RTAS Real Time Clock
 *
 * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
 * Copyright 2014 David Gibson, Red Hat.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */
#include "cpu.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "hw/ppc/spapr.h"
#include "qapi-event.h"

#define SPAPR_RTC(obj) \
    OBJECT_CHECK(sPAPRRTCState, (obj), TYPE_SPAPR_RTC)

typedef struct sPAPRRTCState sPAPRRTCState;
struct sPAPRRTCState {
    /*< private >*/
    SysBusDevice parent_obj;
    int64_t ns_offset;
};

void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns)
{
    sPAPRRTCState *rtc = SPAPR_RTC(dev);
    int64_t host_ns = qemu_clock_get_ns(rtc_clock);
    int64_t guest_ns;
    time_t guest_s;

    assert(rtc);

    guest_ns = host_ns + rtc->ns_offset;
    guest_s = guest_ns / NSEC_PER_SEC;

    if (tm) {
        gmtime_r(&guest_s, tm);
    }
    if (ns) {
        *ns = guest_ns;
    }
}

int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset)
{
    sPAPRRTCState *rtc;

    if (!dev) {
        return -ENODEV;
    }

    rtc = SPAPR_RTC(dev);

    rtc->ns_offset = legacy_offset * NSEC_PER_SEC;

    return 0;
}

static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                 uint32_t token, uint32_t nargs,
                                 target_ulong args,
                                 uint32_t nret, target_ulong rets)
{
    struct tm tm;
    uint32_t ns;

    if ((nargs != 0) || (nret != 8)) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    if (!spapr->rtc) {
        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
        return;
    }

    spapr_rtc_read(spapr->rtc, &tm, &ns);

    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    rtas_st(rets, 1, tm.tm_year + 1900);
    rtas_st(rets, 2, tm.tm_mon + 1);
    rtas_st(rets, 3, tm.tm_mday);
    rtas_st(rets, 4, tm.tm_hour);
    rtas_st(rets, 5, tm.tm_min);
    rtas_st(rets, 6, tm.tm_sec);
    rtas_st(rets, 7, ns);
}

static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                 uint32_t token, uint32_t nargs,
                                 target_ulong args,
                                 uint32_t nret, target_ulong rets)
{
    sPAPRRTCState *rtc;
    struct tm tm;
    time_t new_s;
    int64_t host_ns;

    if ((nargs != 7) || (nret != 1)) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    if (!spapr->rtc) {
        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
        return;
    }

    tm.tm_year = rtas_ld(args, 0) - 1900;
    tm.tm_mon = rtas_ld(args, 1) - 1;
    tm.tm_mday = rtas_ld(args, 2);
    tm.tm_hour = rtas_ld(args, 3);
    tm.tm_min = rtas_ld(args, 4);
    tm.tm_sec = rtas_ld(args, 5);

    new_s = mktimegm(&tm);
    if (new_s == -1) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    /* Generate a monitor event for the change */
    qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);

    rtc = SPAPR_RTC(spapr->rtc);

    host_ns = qemu_clock_get_ns(rtc_clock);

    rtc->ns_offset = (new_s * NSEC_PER_SEC) - host_ns;

    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}

static void spapr_rtc_qom_date(Object *obj, struct tm *current_tm, Error **errp)
{
    spapr_rtc_read(DEVICE(obj), current_tm, NULL);
}

static void spapr_rtc_realize(DeviceState *dev, Error **errp)
{
    sPAPRRTCState *rtc = SPAPR_RTC(dev);
    struct tm tm;
    time_t host_s;
    int64_t rtc_ns;

    /* Initialize the RTAS RTC from host time */

    qemu_get_timedate(&tm, 0);
    host_s = mktimegm(&tm);
    rtc_ns = qemu_clock_get_ns(rtc_clock);
    rtc->ns_offset = host_s * NSEC_PER_SEC - rtc_ns;

    object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date, NULL);
}

static const VMStateDescription vmstate_spapr_rtc = {
    .name = "spapr/rtc",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_INT64(ns_offset, sPAPRRTCState),
        VMSTATE_END_OF_LIST()
    },
};

static void spapr_rtc_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = spapr_rtc_realize;
    dc->vmsd = &vmstate_spapr_rtc;

    spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
                        rtas_get_time_of_day);
    spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
                        rtas_set_time_of_day);
}

static const TypeInfo spapr_rtc_info = {
    .name          = TYPE_SPAPR_RTC,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(sPAPRRTCState),
    .class_size = sizeof(XICSStateClass),
    .class_init    = spapr_rtc_class_init,
};

static void spapr_rtc_register_types(void)
{
    type_register_static(&spapr_rtc_info);
}
type_init(spapr_rtc_register_types)
