/*
 * QEMU Floppy disk emulator (Intel 82078)
 *
 * Copyright (c) 2003, 2007 Jocelyn Mayer
 * Copyright (c) 2008 Hervé Poussineau
 *
 * 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 "qemu/osdep.h"
#include "qapi/error.h"
#include "qom/object.h"
#include "hw/sysbus.h"
#include "hw/block/fdc.h"
#include "migration/vmstate.h"
#include "fdc-internal.h"
#include "trace.h"

#define TYPE_SYSBUS_FDC "base-sysbus-fdc"
typedef struct FDCtrlSysBusClass FDCtrlSysBusClass;
typedef struct FDCtrlSysBus FDCtrlSysBus;
DECLARE_OBJ_CHECKERS(FDCtrlSysBus, FDCtrlSysBusClass,
                     SYSBUS_FDC, TYPE_SYSBUS_FDC)

struct FDCtrlSysBusClass {
    /*< private >*/
    SysBusDeviceClass parent_class;
    /*< public >*/

    bool use_strict_io;
};

struct FDCtrlSysBus {
    /*< private >*/
    SysBusDevice parent_obj;
    /*< public >*/

    struct FDCtrl state;
};

static uint64_t fdctrl_read_mem(void *opaque, hwaddr reg, unsigned ize)
{
    return fdctrl_read(opaque, (uint32_t)reg);
}

static void fdctrl_write_mem(void *opaque, hwaddr reg,
                             uint64_t value, unsigned size)
{
    fdctrl_write(opaque, (uint32_t)reg, value);
}

static const MemoryRegionOps fdctrl_mem_ops = {
    .read = fdctrl_read_mem,
    .write = fdctrl_write_mem,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static const MemoryRegionOps fdctrl_mem_strict_ops = {
    .read = fdctrl_read_mem,
    .write = fdctrl_write_mem,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
};

static void fdctrl_external_reset_sysbus(DeviceState *d)
{
    FDCtrlSysBus *sys = SYSBUS_FDC(d);
    FDCtrl *s = &sys->state;

    fdctrl_reset(s, 0);
}

static void fdctrl_handle_tc(void *opaque, int irq, int level)
{
    trace_fdctrl_tc_pulse(level);
}

void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
                        hwaddr mmio_base, DriveInfo **fds)
{
    FDCtrl *fdctrl;
    DeviceState *dev;
    SysBusDevice *sbd;
    FDCtrlSysBus *sys;

    dev = qdev_new("sysbus-fdc");
    sys = SYSBUS_FDC(dev);
    fdctrl = &sys->state;
    fdctrl->dma_chann = dma_chann; /* FIXME */
    sbd = SYS_BUS_DEVICE(dev);
    sysbus_realize_and_unref(sbd, &error_fatal);
    sysbus_connect_irq(sbd, 0, irq);
    sysbus_mmio_map(sbd, 0, mmio_base);

    fdctrl_init_drives(&sys->state.bus, fds);
}

void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
                       DriveInfo **fds, qemu_irq *fdc_tc)
{
    DeviceState *dev;
    FDCtrlSysBus *sys;

    dev = qdev_new("sun-fdtwo");
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    sys = SYSBUS_FDC(dev);
    sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq);
    sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base);
    *fdc_tc = qdev_get_gpio_in(dev, 0);

    fdctrl_init_drives(&sys->state.bus, fds);
}

static void sysbus_fdc_common_instance_init(Object *obj)
{
    DeviceState *dev = DEVICE(obj);
    FDCtrlSysBusClass *sbdc = SYSBUS_FDC_GET_CLASS(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    FDCtrlSysBus *sys = SYSBUS_FDC(obj);
    FDCtrl *fdctrl = &sys->state;

    qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */

    memory_region_init_io(&fdctrl->iomem, obj,
                          sbdc->use_strict_io ? &fdctrl_mem_strict_ops
                                              : &fdctrl_mem_ops,
                          fdctrl, "fdc", 0x08);
    sysbus_init_mmio(sbd, &fdctrl->iomem);

    sysbus_init_irq(sbd, &fdctrl->irq);
    qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
}

static void sysbus_fdc_realize(DeviceState *dev, Error **errp)
{
    FDCtrlSysBus *sys = SYSBUS_FDC(dev);
    FDCtrl *fdctrl = &sys->state;

    fdctrl_realize_common(dev, fdctrl, errp);
}

static const VMStateDescription vmstate_sysbus_fdc = {
    .name = "fdc",
    .version_id = 2,
    .minimum_version_id = 2,
    .fields = (VMStateField[]) {
        VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl),
        VMSTATE_END_OF_LIST()
    }
};

static void sysbus_fdc_common_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->realize = sysbus_fdc_realize;
    dc->reset = fdctrl_external_reset_sysbus;
    dc->vmsd = &vmstate_sysbus_fdc;
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}

static const TypeInfo sysbus_fdc_common_typeinfo = {
    .name          = TYPE_SYSBUS_FDC,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(FDCtrlSysBus),
    .instance_init = sysbus_fdc_common_instance_init,
    .abstract      = true,
    .class_init    = sysbus_fdc_common_class_init,
    .class_size    = sizeof(FDCtrlSysBusClass),
};

static Property sysbus_fdc_properties[] = {
    DEFINE_PROP_SIGNED("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
                        FloppyDriveType),
    DEFINE_PROP_SIGNED("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
                        FloppyDriveType),
    DEFINE_PROP_SIGNED("fallback", FDCtrlSysBus, state.fallback,
                        FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
                        FloppyDriveType),
    DEFINE_PROP_END_OF_LIST(),
};

static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->desc = "virtual floppy controller";
    device_class_set_props(dc, sysbus_fdc_properties);
}

static const TypeInfo sysbus_fdc_typeinfo = {
    .name          = "sysbus-fdc",
    .parent        = TYPE_SYSBUS_FDC,
    .class_init    = sysbus_fdc_class_init,
};

static Property sun4m_fdc_properties[] = {
    DEFINE_PROP_SIGNED("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
                        FloppyDriveType),
    DEFINE_PROP_SIGNED("fallback", FDCtrlSysBus, state.fallback,
                        FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
                        FloppyDriveType),
    DEFINE_PROP_END_OF_LIST(),
};

static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
{
    FDCtrlSysBusClass *sbdc = SYSBUS_FDC_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    sbdc->use_strict_io = true;
    dc->desc = "virtual floppy controller";
    device_class_set_props(dc, sun4m_fdc_properties);
}

static const TypeInfo sun4m_fdc_typeinfo = {
    .name          = "sun-fdtwo",
    .parent        = TYPE_SYSBUS_FDC,
    .class_init    = sun4m_fdc_class_init,
};

static void sysbus_fdc_register_types(void)
{
    type_register_static(&sysbus_fdc_common_typeinfo);
    type_register_static(&sysbus_fdc_typeinfo);
    type_register_static(&sun4m_fdc_typeinfo);
}

type_init(sysbus_fdc_register_types)
