Statistics
| Branch: | Revision:

root / hw / ide / mmio.c @ 2c9b15ca

History | View | Annotate | Download (5.1 kB)

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
#include "hw/hw.h"
26
#include "hw/sysbus.h"
27
#include "block/block.h"
28
#include "sysemu/dma.h"
29

    
30
#include <hw/ide/internal.h>
31

    
32
/***********************************************************/
33
/* MMIO based ide port
34
 * This emulates IDE device connected directly to the CPU bus without
35
 * dedicated ide controller, which is often seen on embedded boards.
36
 */
37

    
38
#define TYPE_MMIO_IDE "mmio-ide"
39
#define MMIO_IDE(obj) OBJECT_CHECK(MMIOState, (obj), TYPE_MMIO_IDE)
40

    
41
typedef struct MMIOIDEState {
42
    /*< private >*/
43
    SysBusDevice parent_obj;
44
    /*< public >*/
45

    
46
    IDEBus bus;
47

    
48
    uint32_t shift;
49
    qemu_irq irq;
50
    MemoryRegion iomem1, iomem2;
51
} MMIOState;
52

    
53
static void mmio_ide_reset(DeviceState *dev)
54
{
55
    MMIOState *s = MMIO_IDE(dev);
56

    
57
    ide_bus_reset(&s->bus);
58
}
59

    
60
static uint64_t mmio_ide_read(void *opaque, hwaddr addr,
61
                              unsigned size)
62
{
63
    MMIOState *s = opaque;
64
    addr >>= s->shift;
65
    if (addr & 7)
66
        return ide_ioport_read(&s->bus, addr);
67
    else
68
        return ide_data_readw(&s->bus, 0);
69
}
70

    
71
static void mmio_ide_write(void *opaque, hwaddr addr,
72
                           uint64_t val, unsigned size)
73
{
74
    MMIOState *s = opaque;
75
    addr >>= s->shift;
76
    if (addr & 7)
77
        ide_ioport_write(&s->bus, addr, val);
78
    else
79
        ide_data_writew(&s->bus, 0, val);
80
}
81

    
82
static const MemoryRegionOps mmio_ide_ops = {
83
    .read = mmio_ide_read,
84
    .write = mmio_ide_write,
85
    .endianness = DEVICE_NATIVE_ENDIAN,
86
};
87

    
88
static uint64_t mmio_ide_status_read(void *opaque, hwaddr addr,
89
                                     unsigned size)
90
{
91
    MMIOState *s= opaque;
92
    return ide_status_read(&s->bus, 0);
93
}
94

    
95
static void mmio_ide_cmd_write(void *opaque, hwaddr addr,
96
                               uint64_t val, unsigned size)
97
{
98
    MMIOState *s = opaque;
99
    ide_cmd_write(&s->bus, 0, val);
100
}
101

    
102
static const MemoryRegionOps mmio_ide_cs_ops = {
103
    .read = mmio_ide_status_read,
104
    .write = mmio_ide_cmd_write,
105
    .endianness = DEVICE_NATIVE_ENDIAN,
106
};
107

    
108
static const VMStateDescription vmstate_ide_mmio = {
109
    .name = "mmio-ide",
110
    .version_id = 3,
111
    .minimum_version_id = 0,
112
    .minimum_version_id_old = 0,
113
    .fields      = (VMStateField []) {
114
        VMSTATE_IDE_BUS(bus, MMIOState),
115
        VMSTATE_IDE_DRIVES(bus.ifs, MMIOState),
116
        VMSTATE_END_OF_LIST()
117
    }
118
};
119

    
120
static void mmio_ide_realizefn(DeviceState *dev, Error **errp)
121
{
122
    SysBusDevice *d = SYS_BUS_DEVICE(dev);
123
    MMIOState *s = MMIO_IDE(dev);
124

    
125
    ide_init2(&s->bus, s->irq);
126

    
127
    memory_region_init_io(&s->iomem1, NULL, &mmio_ide_ops, s,
128
                          "ide-mmio.1", 16 << s->shift);
129
    memory_region_init_io(&s->iomem2, NULL, &mmio_ide_cs_ops, s,
130
                          "ide-mmio.2", 2 << s->shift);
131
    sysbus_init_mmio(d, &s->iomem1);
132
    sysbus_init_mmio(d, &s->iomem2);
133
}
134

    
135
static void mmio_ide_initfn(Object *obj)
136
{
137
    SysBusDevice *d = SYS_BUS_DEVICE(obj);
138
    MMIOState *s = MMIO_IDE(obj);
139

    
140
    ide_bus_new(&s->bus, DEVICE(obj), 0, 2);
141
    sysbus_init_irq(d, &s->irq);
142
}
143

    
144
static Property mmio_ide_properties[] = {
145
    DEFINE_PROP_UINT32("shift", MMIOState, shift, 0),
146
    DEFINE_PROP_END_OF_LIST()
147
};
148

    
149
static void mmio_ide_class_init(ObjectClass *oc, void *data)
150
{
151
    DeviceClass *dc = DEVICE_CLASS(oc);
152

    
153
    dc->realize = mmio_ide_realizefn;
154
    dc->reset = mmio_ide_reset;
155
    dc->props = mmio_ide_properties;
156
    dc->vmsd = &vmstate_ide_mmio;
157
}
158

    
159
static const TypeInfo mmio_ide_type_info = {
160
    .name = TYPE_MMIO_IDE,
161
    .parent = TYPE_SYS_BUS_DEVICE,
162
    .instance_size = sizeof(MMIOState),
163
    .instance_init = mmio_ide_initfn,
164
    .class_init = mmio_ide_class_init,
165
};
166

    
167
static void mmio_ide_register_types(void)
168
{
169
    type_register_static(&mmio_ide_type_info);
170
}
171

    
172
void mmio_ide_init_drives(DeviceState *dev, DriveInfo *hd0, DriveInfo *hd1)
173
{
174
    MMIOState *s = MMIO_IDE(dev);
175

    
176
    if (hd0 != NULL) {
177
        ide_create_drive(&s->bus, 0, hd0);
178
    }
179
    if (hd1 != NULL) {
180
        ide_create_drive(&s->bus, 1, hd1);
181
    }
182
}
183

    
184
type_init(mmio_ide_register_types)