qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

mmio.c (5371B)


      1 /*
      2  * QEMU IDE Emulation: mmio support (for embedded).
      3  *
      4  * Copyright (c) 2003 Fabrice Bellard
      5  * Copyright (c) 2006 Openedhand Ltd.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23  * THE SOFTWARE.
     24  */
     25 
     26 #include "qemu/osdep.h"
     27 #include "hw/sysbus.h"
     28 #include "migration/vmstate.h"
     29 #include "qemu/module.h"
     30 #include "sysemu/dma.h"
     31 
     32 #include "hw/ide/internal.h"
     33 #include "hw/qdev-properties.h"
     34 #include "qom/object.h"
     35 
     36 /***********************************************************/
     37 /* MMIO based ide port
     38  * This emulates IDE device connected directly to the CPU bus without
     39  * dedicated ide controller, which is often seen on embedded boards.
     40  */
     41 
     42 #define TYPE_MMIO_IDE "mmio-ide"
     43 typedef struct MMIOIDEState MMIOState;
     44 DECLARE_INSTANCE_CHECKER(MMIOState, MMIO_IDE,
     45                          TYPE_MMIO_IDE)
     46 
     47 struct MMIOIDEState {
     48     /*< private >*/
     49     SysBusDevice parent_obj;
     50     /*< public >*/
     51 
     52     IDEBus bus;
     53 
     54     uint32_t shift;
     55     qemu_irq irq;
     56     MemoryRegion iomem1, iomem2;
     57 };
     58 
     59 static void mmio_ide_reset(DeviceState *dev)
     60 {
     61     MMIOState *s = MMIO_IDE(dev);
     62 
     63     ide_bus_reset(&s->bus);
     64 }
     65 
     66 static uint64_t mmio_ide_read(void *opaque, hwaddr addr,
     67                               unsigned size)
     68 {
     69     MMIOState *s = opaque;
     70     addr >>= s->shift;
     71     if (addr & 7)
     72         return ide_ioport_read(&s->bus, addr);
     73     else
     74         return ide_data_readw(&s->bus, 0);
     75 }
     76 
     77 static void mmio_ide_write(void *opaque, hwaddr addr,
     78                            uint64_t val, unsigned size)
     79 {
     80     MMIOState *s = opaque;
     81     addr >>= s->shift;
     82     if (addr & 7)
     83         ide_ioport_write(&s->bus, addr, val);
     84     else
     85         ide_data_writew(&s->bus, 0, val);
     86 }
     87 
     88 static const MemoryRegionOps mmio_ide_ops = {
     89     .read = mmio_ide_read,
     90     .write = mmio_ide_write,
     91     .endianness = DEVICE_LITTLE_ENDIAN,
     92 };
     93 
     94 static uint64_t mmio_ide_status_read(void *opaque, hwaddr addr,
     95                                      unsigned size)
     96 {
     97     MMIOState *s= opaque;
     98     return ide_status_read(&s->bus, 0);
     99 }
    100 
    101 static void mmio_ide_ctrl_write(void *opaque, hwaddr addr,
    102                                 uint64_t val, unsigned size)
    103 {
    104     MMIOState *s = opaque;
    105     ide_ctrl_write(&s->bus, 0, val);
    106 }
    107 
    108 static const MemoryRegionOps mmio_ide_cs_ops = {
    109     .read = mmio_ide_status_read,
    110     .write = mmio_ide_ctrl_write,
    111     .endianness = DEVICE_LITTLE_ENDIAN,
    112 };
    113 
    114 static const VMStateDescription vmstate_ide_mmio = {
    115     .name = "mmio-ide",
    116     .version_id = 3,
    117     .minimum_version_id = 0,
    118     .fields = (VMStateField[]) {
    119         VMSTATE_IDE_BUS(bus, MMIOState),
    120         VMSTATE_IDE_DRIVES(bus.ifs, MMIOState),
    121         VMSTATE_END_OF_LIST()
    122     }
    123 };
    124 
    125 static void mmio_ide_realizefn(DeviceState *dev, Error **errp)
    126 {
    127     SysBusDevice *d = SYS_BUS_DEVICE(dev);
    128     MMIOState *s = MMIO_IDE(dev);
    129 
    130     ide_init2(&s->bus, s->irq);
    131 
    132     memory_region_init_io(&s->iomem1, OBJECT(s), &mmio_ide_ops, s,
    133                           "ide-mmio.1", 16 << s->shift);
    134     memory_region_init_io(&s->iomem2, OBJECT(s), &mmio_ide_cs_ops, s,
    135                           "ide-mmio.2", 2 << s->shift);
    136     sysbus_init_mmio(d, &s->iomem1);
    137     sysbus_init_mmio(d, &s->iomem2);
    138 }
    139 
    140 static void mmio_ide_initfn(Object *obj)
    141 {
    142     SysBusDevice *d = SYS_BUS_DEVICE(obj);
    143     MMIOState *s = MMIO_IDE(obj);
    144 
    145     ide_bus_init(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
    146     sysbus_init_irq(d, &s->irq);
    147 }
    148 
    149 static Property mmio_ide_properties[] = {
    150     DEFINE_PROP_UINT32("shift", MMIOState, shift, 0),
    151     DEFINE_PROP_END_OF_LIST()
    152 };
    153 
    154 static void mmio_ide_class_init(ObjectClass *oc, void *data)
    155 {
    156     DeviceClass *dc = DEVICE_CLASS(oc);
    157 
    158     dc->realize = mmio_ide_realizefn;
    159     dc->reset = mmio_ide_reset;
    160     device_class_set_props(dc, mmio_ide_properties);
    161     dc->vmsd = &vmstate_ide_mmio;
    162 }
    163 
    164 static const TypeInfo mmio_ide_type_info = {
    165     .name = TYPE_MMIO_IDE,
    166     .parent = TYPE_SYS_BUS_DEVICE,
    167     .instance_size = sizeof(MMIOState),
    168     .instance_init = mmio_ide_initfn,
    169     .class_init = mmio_ide_class_init,
    170 };
    171 
    172 static void mmio_ide_register_types(void)
    173 {
    174     type_register_static(&mmio_ide_type_info);
    175 }
    176 
    177 void mmio_ide_init_drives(DeviceState *dev, DriveInfo *hd0, DriveInfo *hd1)
    178 {
    179     MMIOState *s = MMIO_IDE(dev);
    180 
    181     if (hd0 != NULL) {
    182         ide_create_drive(&s->bus, 0, hd0);
    183     }
    184     if (hd1 != NULL) {
    185         ide_create_drive(&s->bus, 1, hd1);
    186     }
    187 }
    188 
    189 type_init(mmio_ide_register_types)