|
|
1.1 root 1: /*
2: * ide bus support for qdev.
3: *
4: * Copyright (c) 2009 Gerd Hoffmann <[email protected]>
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/hw.h>
20: #include "dma.h"
1.1.1.3 root 21: #include "qemu-error.h"
1.1 root 22: #include <hw/ide/internal.h>
1.1.1.4 root 23: #include "blockdev.h"
24: #include "sysemu.h"
1.1 root 25:
26: /* --------------------------------- */
27:
1.1.1.4 root 28: static char *idebus_get_fw_dev_path(DeviceState *dev);
29:
1.1 root 30: static struct BusInfo ide_bus_info = {
31: .name = "IDE",
32: .size = sizeof(IDEBus),
1.1.1.4 root 33: .get_fw_dev_path = idebus_get_fw_dev_path,
1.1.1.5 ! root 34: .props = (Property[]) {
! 35: DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
! 36: DEFINE_PROP_END_OF_LIST(),
! 37: },
1.1 root 38: };
39:
1.1.1.4 root 40: void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id)
1.1 root 41: {
42: qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL);
1.1.1.4 root 43: idebus->bus_id = bus_id;
44: }
45:
46: static char *idebus_get_fw_dev_path(DeviceState *dev)
47: {
48: char path[30];
49:
50: snprintf(path, sizeof(path), "%s@%d", qdev_fw_name(dev),
51: ((IDEBus*)dev->parent_bus)->bus_id);
52:
53: return strdup(path);
1.1 root 54: }
55:
56: static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)
57: {
58: IDEDevice *dev = DO_UPCAST(IDEDevice, qdev, qdev);
59: IDEDeviceInfo *info = DO_UPCAST(IDEDeviceInfo, qdev, base);
60: IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
61:
1.1.1.3 root 62: if (!dev->conf.bs) {
63: error_report("No drive specified");
1.1 root 64: goto err;
65: }
66: if (dev->unit == -1) {
67: dev->unit = bus->master ? 1 : 0;
68: }
69: switch (dev->unit) {
70: case 0:
71: if (bus->master) {
1.1.1.3 root 72: error_report("IDE unit %d is in use", dev->unit);
1.1 root 73: goto err;
74: }
75: bus->master = dev;
76: break;
77: case 1:
78: if (bus->slave) {
1.1.1.3 root 79: error_report("IDE unit %d is in use", dev->unit);
1.1 root 80: goto err;
81: }
82: bus->slave = dev;
83: break;
84: default:
1.1.1.3 root 85: error_report("Invalid IDE unit %d", dev->unit);
1.1 root 86: goto err;
87: }
88: return info->init(dev);
89:
90: err:
91: return -1;
92: }
93:
94: static void ide_qdev_register(IDEDeviceInfo *info)
95: {
96: info->qdev.init = ide_qdev_init;
97: info->qdev.bus_info = &ide_bus_info;
98: qdev_register(&info->qdev);
99: }
100:
101: IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
102: {
103: DeviceState *dev;
104:
1.1.1.5 ! root 105: dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
1.1 root 106: qdev_prop_set_uint32(dev, "unit", unit);
1.1.1.3 root 107: qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv);
108: qdev_init_nofail(dev);
1.1 root 109: return DO_UPCAST(IDEDevice, qdev, dev);
110: }
111:
1.1.1.3 root 112: void ide_get_bs(BlockDriverState *bs[], BusState *qbus)
113: {
114: IDEBus *bus = DO_UPCAST(IDEBus, qbus, qbus);
115: bs[0] = bus->master ? bus->master->conf.bs : NULL;
116: bs[1] = bus->slave ? bus->slave->conf.bs : NULL;
117: }
118:
1.1 root 119: /* --------------------------------- */
120:
121: typedef struct IDEDrive {
122: IDEDevice dev;
123: } IDEDrive;
124:
1.1.1.5 ! root 125: static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
1.1 root 126: {
127: IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
1.1.1.3 root 128: IDEState *s = bus->ifs + dev->unit;
129: const char *serial;
130: DriveInfo *dinfo;
131:
1.1.1.5 ! root 132: if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) {
! 133: error_report("discard_granularity must be 512 for ide");
! 134: return -1;
! 135: }
! 136:
1.1.1.3 root 137: serial = dev->serial;
138: if (!serial) {
139: /* try to fall back to value set with legacy -drive serial=... */
140: dinfo = drive_get_by_blockdev(dev->conf.bs);
141: if (*dinfo->serial) {
142: serial = dinfo->serial;
143: }
144: }
145:
1.1.1.5 ! root 146: if (ide_init_drive(s, dev->conf.bs, kind, dev->version, serial) < 0) {
1.1.1.3 root 147: return -1;
148: }
149:
150: if (!dev->version) {
151: dev->version = qemu_strdup(s->version);
152: }
153: if (!dev->serial) {
154: dev->serial = qemu_strdup(s->drive_serial_str);
155: }
1.1.1.4 root 156:
157: add_boot_device_path(dev->conf.bootindex, &dev->qdev,
158: dev->unit ? "/disk@1" : "/disk@0");
159:
1.1 root 160: return 0;
161: }
162:
1.1.1.5 ! root 163: static int ide_hd_initfn(IDEDevice *dev)
! 164: {
! 165: return ide_dev_initfn(dev, IDE_HD);
! 166: }
! 167:
! 168: static int ide_cd_initfn(IDEDevice *dev)
! 169: {
! 170: return ide_dev_initfn(dev, IDE_CD);
! 171: }
! 172:
! 173: static int ide_drive_initfn(IDEDevice *dev)
! 174: {
! 175: DriveInfo *dinfo = drive_get_by_blockdev(dev->conf.bs);
! 176:
! 177: return ide_dev_initfn(dev, dinfo->media_cd ? IDE_CD : IDE_HD);
! 178: }
! 179:
! 180: #define DEFINE_IDE_DEV_PROPERTIES() \
! 181: DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
! 182: DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
! 183: DEFINE_PROP_STRING("serial", IDEDrive, dev.serial)
! 184:
! 185: static IDEDeviceInfo ide_dev_info[] = {
! 186: {
! 187: .qdev.name = "ide-hd",
! 188: .qdev.fw_name = "drive",
! 189: .qdev.desc = "virtual IDE disk",
! 190: .qdev.size = sizeof(IDEDrive),
! 191: .init = ide_hd_initfn,
! 192: .qdev.props = (Property[]) {
! 193: DEFINE_IDE_DEV_PROPERTIES(),
! 194: DEFINE_PROP_END_OF_LIST(),
! 195: }
! 196: },{
! 197: .qdev.name = "ide-cd",
! 198: .qdev.fw_name = "drive",
! 199: .qdev.desc = "virtual IDE CD-ROM",
! 200: .qdev.size = sizeof(IDEDrive),
! 201: .init = ide_cd_initfn,
! 202: .qdev.props = (Property[]) {
! 203: DEFINE_IDE_DEV_PROPERTIES(),
! 204: DEFINE_PROP_END_OF_LIST(),
! 205: }
! 206: },{
! 207: .qdev.name = "ide-drive", /* legacy -device ide-drive */
! 208: .qdev.fw_name = "drive",
! 209: .qdev.desc = "virtual IDE disk or CD-ROM (legacy)",
! 210: .qdev.size = sizeof(IDEDrive),
! 211: .init = ide_drive_initfn,
! 212: .qdev.props = (Property[]) {
! 213: DEFINE_IDE_DEV_PROPERTIES(),
! 214: DEFINE_PROP_END_OF_LIST(),
! 215: }
1.1 root 216: }
217: };
218:
1.1.1.5 ! root 219: static void ide_dev_register(void)
1.1 root 220: {
1.1.1.5 ! root 221: int i;
! 222:
! 223: for (i = 0; i < ARRAY_SIZE(ide_dev_info); i++) {
! 224: ide_qdev_register(&ide_dev_info[i]);
! 225: }
1.1 root 226: }
1.1.1.5 ! root 227: device_init(ide_dev_register);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.