~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to hw/ide/qdev.c

  • Committer: Phil Dennis-Jordan
  • Author(s): Michael Tokarev
  • Date: 2017-05-23 06:58:03 UTC
  • Revision ID: phil@philjordan.eu-20170523065803-3subwvf3y8kzkjry
Tags: upstream-2.8+dfsg
ImportĀ upstreamĀ versionĀ 2.8+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ide 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 "qemu/osdep.h"
 
20
#include "hw/hw.h"
 
21
#include "sysemu/dma.h"
 
22
#include "qapi/error.h"
 
23
#include "qemu/error-report.h"
 
24
#include "hw/ide/internal.h"
 
25
#include "sysemu/block-backend.h"
 
26
#include "sysemu/blockdev.h"
 
27
#include "hw/block/block.h"
 
28
#include "sysemu/sysemu.h"
 
29
#include "qapi/visitor.h"
 
30
 
 
31
/* --------------------------------- */
 
32
 
 
33
static char *idebus_get_fw_dev_path(DeviceState *dev);
 
34
static void idebus_unrealize(DeviceState *qdev, Error **errp);
 
35
 
 
36
static Property ide_props[] = {
 
37
    DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
 
38
    DEFINE_PROP_END_OF_LIST(),
 
39
};
 
40
 
 
41
static void ide_bus_class_init(ObjectClass *klass, void *data)
 
42
{
 
43
    BusClass *k = BUS_CLASS(klass);
 
44
 
 
45
    k->get_fw_dev_path = idebus_get_fw_dev_path;
 
46
}
 
47
 
 
48
static void idebus_unrealize(DeviceState *qdev, Error **errp)
 
49
{
 
50
    IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
 
51
 
 
52
    if (bus->vmstate) {
 
53
        qemu_del_vm_change_state_handler(bus->vmstate);
 
54
    }
 
55
}
 
56
 
 
57
static const TypeInfo ide_bus_info = {
 
58
    .name = TYPE_IDE_BUS,
 
59
    .parent = TYPE_BUS,
 
60
    .instance_size = sizeof(IDEBus),
 
61
    .class_init = ide_bus_class_init,
 
62
};
 
63
 
 
64
void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
 
65
                 int bus_id, int max_units)
 
66
{
 
67
    qbus_create_inplace(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL);
 
68
    idebus->bus_id = bus_id;
 
69
    idebus->max_units = max_units;
 
70
}
 
71
 
 
72
static char *idebus_get_fw_dev_path(DeviceState *dev)
 
73
{
 
74
    char path[30];
 
75
 
 
76
    snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev),
 
77
             ((IDEBus*)dev->parent_bus)->bus_id);
 
78
 
 
79
    return g_strdup(path);
 
80
}
 
81
 
 
82
static int ide_qdev_init(DeviceState *qdev)
 
83
{
 
84
    IDEDevice *dev = IDE_DEVICE(qdev);
 
85
    IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
 
86
    IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
 
87
 
 
88
    if (dev->unit == -1) {
 
89
        dev->unit = bus->master ? 1 : 0;
 
90
    }
 
91
 
 
92
    if (dev->unit >= bus->max_units) {
 
93
        error_report("Can't create IDE unit %d, bus supports only %d units",
 
94
                     dev->unit, bus->max_units);
 
95
        goto err;
 
96
    }
 
97
 
 
98
    switch (dev->unit) {
 
99
    case 0:
 
100
        if (bus->master) {
 
101
            error_report("IDE unit %d is in use", dev->unit);
 
102
            goto err;
 
103
        }
 
104
        bus->master = dev;
 
105
        break;
 
106
    case 1:
 
107
        if (bus->slave) {
 
108
            error_report("IDE unit %d is in use", dev->unit);
 
109
            goto err;
 
110
        }
 
111
        bus->slave = dev;
 
112
        break;
 
113
    default:
 
114
        error_report("Invalid IDE unit %d", dev->unit);
 
115
        goto err;
 
116
    }
 
117
    return dc->init(dev);
 
118
 
 
119
err:
 
120
    return -1;
 
121
}
 
122
 
 
123
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
 
124
{
 
125
    DeviceState *dev;
 
126
 
 
127
    dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
 
128
    qdev_prop_set_uint32(dev, "unit", unit);
 
129
    qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(drive),
 
130
                        &error_fatal);
 
131
    qdev_init_nofail(dev);
 
132
    return DO_UPCAST(IDEDevice, qdev, dev);
 
133
}
 
134
 
 
135
int ide_get_geometry(BusState *bus, int unit,
 
136
                     int16_t *cyls, int8_t *heads, int8_t *secs)
 
137
{
 
138
    IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit];
 
139
 
 
140
    if (s->drive_kind != IDE_HD || !s->blk) {
 
141
        return -1;
 
142
    }
 
143
 
 
144
    *cyls = s->cylinders;
 
145
    *heads = s->heads;
 
146
    *secs = s->sectors;
 
147
    return 0;
 
148
}
 
149
 
 
150
int ide_get_bios_chs_trans(BusState *bus, int unit)
 
151
{
 
152
    return DO_UPCAST(IDEBus, qbus, bus)->ifs[unit].chs_trans;
 
153
}
 
154
 
 
155
/* --------------------------------- */
 
156
 
 
157
typedef struct IDEDrive {
 
158
    IDEDevice dev;
 
159
} IDEDrive;
 
160
 
 
161
static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
 
162
{
 
163
    IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
 
164
    IDEState *s = bus->ifs + dev->unit;
 
165
    Error *err = NULL;
 
166
 
 
167
    if (!dev->conf.blk) {
 
168
        if (kind != IDE_CD) {
 
169
            error_report("No drive specified");
 
170
            return -1;
 
171
        } else {
 
172
            /* Anonymous BlockBackend for an empty drive */
 
173
            dev->conf.blk = blk_new();
 
174
        }
 
175
    }
 
176
 
 
177
    if (dev->conf.discard_granularity == -1) {
 
178
        dev->conf.discard_granularity = 512;
 
179
    } else if (dev->conf.discard_granularity &&
 
180
               dev->conf.discard_granularity != 512) {
 
181
        error_report("discard_granularity must be 512 for ide");
 
182
        return -1;
 
183
    }
 
184
 
 
185
    blkconf_blocksizes(&dev->conf);
 
186
    if (dev->conf.logical_block_size != 512) {
 
187
        error_report("logical_block_size must be 512 for IDE");
 
188
        return -1;
 
189
    }
 
190
 
 
191
    blkconf_serial(&dev->conf, &dev->serial);
 
192
    if (kind != IDE_CD) {
 
193
        blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err);
 
194
        if (err) {
 
195
            error_report_err(err);
 
196
            return -1;
 
197
        }
 
198
    }
 
199
    blkconf_apply_backend_options(&dev->conf);
 
200
 
 
201
    if (ide_init_drive(s, dev->conf.blk, kind,
 
202
                       dev->version, dev->serial, dev->model, dev->wwn,
 
203
                       dev->conf.cyls, dev->conf.heads, dev->conf.secs,
 
204
                       dev->chs_trans) < 0) {
 
205
        return -1;
 
206
    }
 
207
 
 
208
    if (!dev->version) {
 
209
        dev->version = g_strdup(s->version);
 
210
    }
 
211
    if (!dev->serial) {
 
212
        dev->serial = g_strdup(s->drive_serial_str);
 
213
    }
 
214
 
 
215
    add_boot_device_path(dev->conf.bootindex, &dev->qdev,
 
216
                         dev->unit ? "/disk@1" : "/disk@0");
 
217
 
 
218
    return 0;
 
219
}
 
220
 
 
221
static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name,
 
222
                                  void *opaque, Error **errp)
 
223
{
 
224
    IDEDevice *d = IDE_DEVICE(obj);
 
225
 
 
226
    visit_type_int32(v, name, &d->conf.bootindex, errp);
 
227
}
 
228
 
 
229
static void ide_dev_set_bootindex(Object *obj, Visitor *v, const char *name,
 
230
                                  void *opaque, Error **errp)
 
231
{
 
232
    IDEDevice *d = IDE_DEVICE(obj);
 
233
    int32_t boot_index;
 
234
    Error *local_err = NULL;
 
235
 
 
236
    visit_type_int32(v, name, &boot_index, &local_err);
 
237
    if (local_err) {
 
238
        goto out;
 
239
    }
 
240
    /* check whether bootindex is present in fw_boot_order list  */
 
241
    check_boot_index(boot_index, &local_err);
 
242
    if (local_err) {
 
243
        goto out;
 
244
    }
 
245
    /* change bootindex to a new one */
 
246
    d->conf.bootindex = boot_index;
 
247
 
 
248
    if (d->unit != -1) {
 
249
        add_boot_device_path(d->conf.bootindex, &d->qdev,
 
250
                             d->unit ? "/disk@1" : "/disk@0");
 
251
    }
 
252
out:
 
253
    error_propagate(errp, local_err);
 
254
}
 
255
 
 
256
static void ide_dev_instance_init(Object *obj)
 
257
{
 
258
    object_property_add(obj, "bootindex", "int32",
 
259
                        ide_dev_get_bootindex,
 
260
                        ide_dev_set_bootindex, NULL, NULL, NULL);
 
261
    object_property_set_int(obj, -1, "bootindex", NULL);
 
262
}
 
263
 
 
264
static int ide_hd_initfn(IDEDevice *dev)
 
265
{
 
266
    return ide_dev_initfn(dev, IDE_HD);
 
267
}
 
268
 
 
269
static int ide_cd_initfn(IDEDevice *dev)
 
270
{
 
271
    return ide_dev_initfn(dev, IDE_CD);
 
272
}
 
273
 
 
274
static int ide_drive_initfn(IDEDevice *dev)
 
275
{
 
276
    DriveInfo *dinfo = NULL;
 
277
 
 
278
    if (dev->conf.blk) {
 
279
        dinfo = blk_legacy_dinfo(dev->conf.blk);
 
280
    }
 
281
 
 
282
    return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
 
283
}
 
284
 
 
285
#define DEFINE_IDE_DEV_PROPERTIES()                     \
 
286
    DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),        \
 
287
    DEFINE_BLOCK_ERROR_PROPERTIES(IDEDrive, dev.conf),  \
 
288
    DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),  \
 
289
    DEFINE_PROP_UINT64("wwn",  IDEDrive, dev.wwn, 0),    \
 
290
    DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial),\
 
291
    DEFINE_PROP_STRING("model", IDEDrive, dev.model)
 
292
 
 
293
static Property ide_hd_properties[] = {
 
294
    DEFINE_IDE_DEV_PROPERTIES(),
 
295
    DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive, dev.conf),
 
296
    DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans",
 
297
                IDEDrive, dev.chs_trans, BIOS_ATA_TRANSLATION_AUTO),
 
298
    DEFINE_PROP_END_OF_LIST(),
 
299
};
 
300
 
 
301
static void ide_hd_class_init(ObjectClass *klass, void *data)
 
302
{
 
303
    DeviceClass *dc = DEVICE_CLASS(klass);
 
304
    IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
 
305
    k->init = ide_hd_initfn;
 
306
    dc->fw_name = "drive";
 
307
    dc->desc = "virtual IDE disk";
 
308
    dc->props = ide_hd_properties;
 
309
}
 
310
 
 
311
static const TypeInfo ide_hd_info = {
 
312
    .name          = "ide-hd",
 
313
    .parent        = TYPE_IDE_DEVICE,
 
314
    .instance_size = sizeof(IDEDrive),
 
315
    .class_init    = ide_hd_class_init,
 
316
};
 
317
 
 
318
static Property ide_cd_properties[] = {
 
319
    DEFINE_IDE_DEV_PROPERTIES(),
 
320
    DEFINE_PROP_END_OF_LIST(),
 
321
};
 
322
 
 
323
static void ide_cd_class_init(ObjectClass *klass, void *data)
 
324
{
 
325
    DeviceClass *dc = DEVICE_CLASS(klass);
 
326
    IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
 
327
    k->init = ide_cd_initfn;
 
328
    dc->fw_name = "drive";
 
329
    dc->desc = "virtual IDE CD-ROM";
 
330
    dc->props = ide_cd_properties;
 
331
}
 
332
 
 
333
static const TypeInfo ide_cd_info = {
 
334
    .name          = "ide-cd",
 
335
    .parent        = TYPE_IDE_DEVICE,
 
336
    .instance_size = sizeof(IDEDrive),
 
337
    .class_init    = ide_cd_class_init,
 
338
};
 
339
 
 
340
static Property ide_drive_properties[] = {
 
341
    DEFINE_IDE_DEV_PROPERTIES(),
 
342
    DEFINE_PROP_END_OF_LIST(),
 
343
};
 
344
 
 
345
static void ide_drive_class_init(ObjectClass *klass, void *data)
 
346
{
 
347
    DeviceClass *dc = DEVICE_CLASS(klass);
 
348
    IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
 
349
    k->init = ide_drive_initfn;
 
350
    dc->fw_name = "drive";
 
351
    dc->desc = "virtual IDE disk or CD-ROM (legacy)";
 
352
    dc->props = ide_drive_properties;
 
353
}
 
354
 
 
355
static const TypeInfo ide_drive_info = {
 
356
    .name          = "ide-drive",
 
357
    .parent        = TYPE_IDE_DEVICE,
 
358
    .instance_size = sizeof(IDEDrive),
 
359
    .class_init    = ide_drive_class_init,
 
360
};
 
361
 
 
362
static void ide_device_class_init(ObjectClass *klass, void *data)
 
363
{
 
364
    DeviceClass *k = DEVICE_CLASS(klass);
 
365
    k->init = ide_qdev_init;
 
366
    set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
 
367
    k->bus_type = TYPE_IDE_BUS;
 
368
    k->unrealize = idebus_unrealize;
 
369
    k->props = ide_props;
 
370
}
 
371
 
 
372
static const TypeInfo ide_device_type_info = {
 
373
    .name = TYPE_IDE_DEVICE,
 
374
    .parent = TYPE_DEVICE,
 
375
    .instance_size = sizeof(IDEDevice),
 
376
    .abstract = true,
 
377
    .class_size = sizeof(IDEDeviceClass),
 
378
    .class_init = ide_device_class_init,
 
379
    .instance_init = ide_dev_instance_init,
 
380
};
 
381
 
 
382
static void ide_register_types(void)
 
383
{
 
384
    type_register_static(&ide_bus_info);
 
385
    type_register_static(&ide_hd_info);
 
386
    type_register_static(&ide_cd_info);
 
387
    type_register_static(&ide_drive_info);
 
388
    type_register_static(&ide_device_type_info);
 
389
}
 
390
 
 
391
type_init(ide_register_types)