Statistics
| Branch: | Revision:

root / hw / isa-bus.c @ 771124e1

History | View | Annotate | Download (6.2 kB)

1
/*
2
 * isa bus support for qdev.
3
 *
4
 * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "hw.h"
20
#include "monitor.h"
21
#include "sysbus.h"
22
#include "isa.h"
23
#include "exec-memory.h"
24

    
25
static ISABus *isabus;
26
target_phys_addr_t isa_mem_base = 0;
27

    
28
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
29
static char *isabus_get_fw_dev_path(DeviceState *dev);
30

    
31
static struct BusInfo isa_bus_info = {
32
    .name      = "ISA",
33
    .size      = sizeof(ISABus),
34
    .print_dev = isabus_dev_print,
35
    .get_fw_dev_path = isabus_get_fw_dev_path,
36
};
37

    
38
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
39
{
40
    if (isabus) {
41
        fprintf(stderr, "Can't create a second ISA bus\n");
42
        return NULL;
43
    }
44
    if (NULL == dev) {
45
        dev = qdev_create(NULL, "isabus-bridge");
46
        qdev_init_nofail(dev);
47
    }
48

    
49
    isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL));
50
    isabus->address_space_io = address_space_io;
51
    return isabus;
52
}
53

    
54
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
55
{
56
    if (!bus) {
57
        hw_error("Can't set isa irqs with no isa bus present.");
58
    }
59
    bus->irqs = irqs;
60
}
61

    
62
/*
63
 * isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
64
 *
65
 * This function is only for special cases such as the 'ferr', and
66
 * temporary use for normal devices until they are converted to qdev.
67
 */
68
qemu_irq isa_get_irq(ISADevice *dev, int isairq)
69
{
70
    assert(!dev || DO_UPCAST(ISABus, qbus, dev->qdev.parent_bus) == isabus);
71
    if (isairq < 0 || isairq > 15) {
72
        hw_error("isa irq %d invalid", isairq);
73
    }
74
    return isabus->irqs[isairq];
75
}
76

    
77
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
78
{
79
    assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
80
    dev->isairq[dev->nirqs] = isairq;
81
    *p = isa_get_irq(dev, isairq);
82
    dev->nirqs++;
83
}
84

    
85
static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
86
{
87
    if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
88
        dev->ioport_id = ioport;
89
    }
90
}
91

    
92
void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
93
{
94
    memory_region_add_subregion(isabus->address_space_io, start, io);
95
    isa_init_ioport(dev, start);
96
}
97

    
98
void isa_register_portio_list(ISADevice *dev, uint16_t start,
99
                              const MemoryRegionPortio *pio_start,
100
                              void *opaque, const char *name)
101
{
102
    PortioList *piolist = g_new(PortioList, 1);
103

    
104
    /* START is how we should treat DEV, regardless of the actual
105
       contents of the portio array.  This is how the old code
106
       actually handled e.g. the FDC device.  */
107
    isa_init_ioport(dev, start);
108

    
109
    portio_list_init(piolist, pio_start, opaque, name);
110
    portio_list_add(piolist, isabus->address_space_io, start);
111
}
112

    
113
static int isa_qdev_init(DeviceState *qdev, DeviceInfo *base)
114
{
115
    ISADevice *dev = ISA_DEVICE(qdev);
116
    ISADeviceClass *klass = ISA_DEVICE_GET_CLASS(dev);
117

    
118
    dev->isairq[0] = -1;
119
    dev->isairq[1] = -1;
120

    
121
    if (klass->init) {
122
        return klass->init(dev);
123
    }
124

    
125
    return 0;
126
}
127

    
128
void isa_qdev_register_subclass(DeviceInfo *info, const char *parent)
129
{
130
    info->init = isa_qdev_init;
131
    info->bus_info = &isa_bus_info;
132
    qdev_register_subclass(info, parent);
133
}
134

    
135
void isa_qdev_register(DeviceInfo *info)
136
{
137
    isa_qdev_register_subclass(info, TYPE_ISA_DEVICE);
138
}
139

    
140
ISADevice *isa_create(ISABus *bus, const char *name)
141
{
142
    DeviceState *dev;
143

    
144
    if (!bus) {
145
        hw_error("Tried to create isa device %s with no isa bus present.",
146
                 name);
147
    }
148
    dev = qdev_create(&bus->qbus, name);
149
    return ISA_DEVICE(dev);
150
}
151

    
152
ISADevice *isa_try_create(ISABus *bus, const char *name)
153
{
154
    DeviceState *dev;
155

    
156
    if (!bus) {
157
        hw_error("Tried to create isa device %s with no isa bus present.",
158
                 name);
159
    }
160
    dev = qdev_try_create(&bus->qbus, name);
161
    return ISA_DEVICE(dev);
162
}
163

    
164
ISADevice *isa_create_simple(ISABus *bus, const char *name)
165
{
166
    ISADevice *dev;
167

    
168
    dev = isa_create(bus, name);
169
    qdev_init_nofail(&dev->qdev);
170
    return dev;
171
}
172

    
173
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
174
{
175
    ISADevice *d = ISA_DEVICE(dev);
176

    
177
    if (d->isairq[1] != -1) {
178
        monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
179
                       d->isairq[0], d->isairq[1]);
180
    } else if (d->isairq[0] != -1) {
181
        monitor_printf(mon, "%*sisa irq %d\n", indent, "",
182
                       d->isairq[0]);
183
    }
184
}
185

    
186
static int isabus_bridge_init(SysBusDevice *dev)
187
{
188
    /* nothing */
189
    return 0;
190
}
191

    
192
static void isabus_bridge_class_init(ObjectClass *klass, void *data)
193
{
194
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
195

    
196
    k->init = isabus_bridge_init;
197
}
198

    
199
static DeviceInfo isabus_bridge_info = {
200
    .name = "isabus-bridge",
201
    .fw_name = "isa",
202
    .size = sizeof(SysBusDevice),
203
    .no_user = 1,
204
    .class_init = isabus_bridge_class_init,
205
};
206

    
207
static TypeInfo isa_device_type_info = {
208
    .name = TYPE_ISA_DEVICE,
209
    .parent = TYPE_DEVICE,
210
    .instance_size = sizeof(ISADevice),
211
    .abstract = true,
212
    .class_size = sizeof(ISADeviceClass),
213
};
214

    
215
static void isabus_register_devices(void)
216
{
217
    sysbus_register_withprop(&isabus_bridge_info);
218
    type_register_static(&isa_device_type_info);
219
}
220

    
221
static char *isabus_get_fw_dev_path(DeviceState *dev)
222
{
223
    ISADevice *d = (ISADevice*)dev;
224
    char path[40];
225
    int off;
226

    
227
    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
228
    if (d->ioport_id) {
229
        snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
230
    }
231

    
232
    return strdup(path);
233
}
234

    
235
MemoryRegion *isa_address_space(ISADevice *dev)
236
{
237
    return get_system_memory();
238
}
239

    
240
device_init(isabus_register_devices)