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.1 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 20 #include "qemu/osdep.h" 21 #include "qapi/error.h" 22 #include "qemu/error-report.h" 23 #include "qemu/module.h" 24 #include "hw/ide/internal.h" 25 #include "sysemu/block-backend.h" 26 #include "sysemu/blockdev.h" 27 #include "sysemu/runstate.h" 28 29 static char *idebus_get_fw_dev_path(DeviceState *dev); 30 static void idebus_unrealize(BusState *qdev); 31 32 static void ide_bus_class_init(ObjectClass *klass, void *data) 33 { 34 BusClass *k = BUS_CLASS(klass); 35 36 k->get_fw_dev_path = idebus_get_fw_dev_path; 37 k->unrealize = idebus_unrealize; 38 } 39 40 static void idebus_unrealize(BusState *bus) 41 { 42 IDEBus *ibus = IDE_BUS(bus); 43 44 if (ibus->vmstate) { 45 qemu_del_vm_change_state_handler(ibus->vmstate); 46 } 47 } 48 49 static const TypeInfo ide_bus_info = { 50 .name = TYPE_IDE_BUS, 51 .parent = TYPE_BUS, 52 .instance_size = sizeof(IDEBus), 53 .class_init = ide_bus_class_init, 54 }; 55 56 void ide_bus_init(IDEBus *idebus, size_t idebus_size, DeviceState *dev, 57 int bus_id, int max_units) 58 { 59 qbus_init(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL); 60 idebus->bus_id = bus_id; 61 idebus->max_units = max_units; 62 } 63 64 static char *idebus_get_fw_dev_path(DeviceState *dev) 65 { 66 char path[30]; 67 68 snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), 69 ((IDEBus *)dev->parent_bus)->bus_id); 70 71 return g_strdup(path); 72 } 73 74 IDEDevice *ide_bus_create_drive(IDEBus *bus, int unit, DriveInfo *drive) 75 { 76 DeviceState *dev; 77 78 dev = qdev_new(drive->media_cd ? "ide-cd" : "ide-hd"); 79 qdev_prop_set_uint32(dev, "unit", unit); 80 qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(drive), 81 &error_fatal); 82 qdev_realize_and_unref(dev, &bus->qbus, &error_fatal); 83 return DO_UPCAST(IDEDevice, qdev, dev); 84 } 85 86 int ide_get_geometry(BusState *bus, int unit, 87 int16_t *cyls, int8_t *heads, int8_t *secs) 88 { 89 IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit]; 90 91 if (s->drive_kind != IDE_HD || !s->blk) { 92 return -1; 93 } 94 95 *cyls = s->cylinders; 96 *heads = s->heads; 97 *secs = s->sectors; 98 return 0; 99 } 100 101 int ide_get_bios_chs_trans(BusState *bus, int unit) 102 { 103 return DO_UPCAST(IDEBus, qbus, bus)->ifs[unit].chs_trans; 104 } 105 106 static void ide_bus_register_type(void) 107 { 108 type_register_static(&ide_bus_info); 109 } 110 111 type_init(ide_bus_register_type) 112