Revision 163c8a59 hw/pci.c

b/hw/pci.c
27 27
#include "net.h"
28 28
#include "sysemu.h"
29 29
#include "loader.h"
30
#include "qemu-objects.h"
30 31

  
31 32
//#define DEBUG_PCI
32 33
#ifdef DEBUG_PCI
......
1076 1077
    { 0, NULL}
1077 1078
};
1078 1079

  
1079
static void pci_info_device(PCIBus *bus, PCIDevice *d)
1080
static void pci_for_each_device_under_bus(PCIBus *bus,
1081
                                          void (*fn)(PCIBus *b, PCIDevice *d))
1080 1082
{
1081
    Monitor *mon = cur_mon;
1082
    int i, class;
1083
    PCIIORegion *r;
1084
    const pci_class_desc *desc;
1083
    PCIDevice *d;
1084
    int devfn;
1085 1085

  
1086
    monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
1087
                   pci_bus_num(d->bus),
1088
                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
1089
    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
1086
    for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
1087
        d = bus->devices[devfn];
1088
        if (d) {
1089
            fn(bus, d);
1090
        }
1091
    }
1092
}
1093

  
1094
void pci_for_each_device(PCIBus *bus, int bus_num,
1095
                         void (*fn)(PCIBus *b, PCIDevice *d))
1096
{
1097
    bus = pci_find_bus(bus, bus_num);
1098

  
1099
    if (bus) {
1100
        pci_for_each_device_under_bus(bus, fn);
1101
    }
1102
}
1103

  
1104
static void pci_device_print(Monitor *mon, QDict *device)
1105
{
1106
    QDict *qdict;
1107
    QListEntry *entry;
1108
    uint64_t addr, size;
1109

  
1110
    monitor_printf(mon, "  Bus %2" PRId64 ", ", qdict_get_int(device, "bus"));
1111
    monitor_printf(mon, "device %3" PRId64 ", function %" PRId64 ":\n",
1112
                        qdict_get_int(device, "slot"),
1113
                        qdict_get_int(device, "function"));
1090 1114
    monitor_printf(mon, "    ");
1091
    desc = pci_class_descriptions;
1092
    while (desc->desc && class != desc->class)
1093
        desc++;
1094
    if (desc->desc) {
1095
        monitor_printf(mon, "%s", desc->desc);
1115

  
1116
    qdict = qdict_get_qdict(device, "class_info");
1117
    if (qdict_haskey(qdict, "desc")) {
1118
        monitor_printf(mon, "%s", qdict_get_str(qdict, "desc"));
1096 1119
    } else {
1097
        monitor_printf(mon, "Class %04x", class);
1120
        monitor_printf(mon, "Class %04" PRId64, qdict_get_int(qdict, "class"));
1098 1121
    }
1099
    monitor_printf(mon, ": PCI device %04x:%04x\n",
1100
           pci_get_word(d->config + PCI_VENDOR_ID),
1101
           pci_get_word(d->config + PCI_DEVICE_ID));
1102 1122

  
1103
    if (d->config[PCI_INTERRUPT_PIN] != 0) {
1104
        monitor_printf(mon, "      IRQ %d.\n",
1105
                       d->config[PCI_INTERRUPT_LINE]);
1123
    qdict = qdict_get_qdict(device, "id");
1124
    monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n",
1125
                        qdict_get_int(qdict, "device"),
1126
                        qdict_get_int(qdict, "vendor"));
1127

  
1128
    if (qdict_haskey(device, "irq")) {
1129
        monitor_printf(mon, "      IRQ %" PRId64 ".\n",
1130
                            qdict_get_int(device, "irq"));
1106 1131
    }
1107
    if (class == 0x0604) {
1108
        uint64_t base;
1109
        uint64_t limit;
1110 1132

  
1111
        monitor_printf(mon, "      BUS %d.\n", d->config[0x19]);
1112
        monitor_printf(mon, "      secondary bus %d.\n",
1113
                       d->config[PCI_SECONDARY_BUS]);
1114
        monitor_printf(mon, "      subordinate bus %d.\n",
1115
                       d->config[PCI_SUBORDINATE_BUS]);
1133
    if (qdict_haskey(device, "pci_bridge")) {
1134
        QDict *info;
1135

  
1136
        qdict = qdict_get_qdict(device, "pci_bridge");
1137

  
1138
        info = qdict_get_qdict(qdict, "bus");
1139
        monitor_printf(mon, "      BUS %" PRId64 ".\n",
1140
                            qdict_get_int(info, "number"));
1141
        monitor_printf(mon, "      secondary bus %" PRId64 ".\n",
1142
                            qdict_get_int(info, "secondary"));
1143
        monitor_printf(mon, "      subordinate bus %" PRId64 ".\n",
1144
                            qdict_get_int(info, "subordinate"));
1116 1145

  
1117
        base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_IO);
1118
        limit = pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_IO);
1146
        info = qdict_get_qdict(qdict, "io_range");
1119 1147
        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
1120
                       base, limit);
1148
                       qdict_get_int(info, "base"),
1149
                       qdict_get_int(info, "limit"));
1121 1150

  
1122
        base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY);
1123
        limit= pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_MEMORY);
1151
        info = qdict_get_qdict(qdict, "memory_range");
1124 1152
        monitor_printf(mon,
1125 1153
                       "      memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
1126
                       base, limit);
1154
                       qdict_get_int(info, "base"),
1155
                       qdict_get_int(info, "limit"));
1127 1156

  
1128
        base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY |
1129
                                   PCI_BASE_ADDRESS_MEM_PREFETCH);
1130
        limit = pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_MEMORY |
1131
                                     PCI_BASE_ADDRESS_MEM_PREFETCH);
1157
        info = qdict_get_qdict(qdict, "prefetchable_range");
1132 1158
        monitor_printf(mon, "      prefetchable memory range "
1133
                       "[0x%08"PRIx64", 0x%08"PRIx64"]\n", base, limit);
1159
                       "[0x%08"PRIx64", 0x%08"PRIx64"]\n",
1160
                       qdict_get_int(info, "base"),
1161
        qdict_get_int(info, "limit"));
1134 1162
    }
1135
    for(i = 0;i < PCI_NUM_REGIONS; i++) {
1136
        r = &d->io_regions[i];
1137
        if (r->size != 0) {
1138
            monitor_printf(mon, "      BAR%d: ", i);
1139
            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
1140
                monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS
1141
                               " [0x%04"FMT_PCIBUS"].\n",
1142
                               r->addr, r->addr + r->size - 1);
1143
            } else {
1144
                const char *type = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64 ?
1145
                    "64 bit" : "32 bit";
1146
                const char *prefetch =
1147
                    r->type & PCI_BASE_ADDRESS_MEM_PREFETCH ?
1148
                    " prefetchable" : "";
1149 1163

  
1150
                monitor_printf(mon, "%s%s memory at 0x%08"FMT_PCIBUS
1164
    QLIST_FOREACH_ENTRY(qdict_get_qlist(device, "regions"), entry) {
1165
        qdict = qobject_to_qdict(qlist_entry_obj(entry));
1166
        monitor_printf(mon, "      BAR%d: ", (int) qdict_get_int(qdict, "bar"));
1167

  
1168
        addr = qdict_get_int(qdict, "address");
1169
        size = qdict_get_int(qdict, "size");
1170

  
1171
        if (!strcmp(qdict_get_str(qdict, "type"), "io")) {
1172
            monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS
1173
                                " [0x%04"FMT_PCIBUS"].\n",
1174
                                addr, addr + size - 1);
1175
        } else {
1176
            monitor_printf(mon, "%d bit%s memory at 0x%08"FMT_PCIBUS
1151 1177
                               " [0x%08"FMT_PCIBUS"].\n",
1152
                               type, prefetch,
1153
                               r->addr, r->addr + r->size - 1);
1154
            }
1178
                                qdict_get_bool(qdict, "mem_type_64") ? 64 : 32,
1179
                                qdict_get_bool(qdict, "prefetch") ?
1180
                                " prefetchable" : "", addr, addr + size - 1);
1155 1181
        }
1156 1182
    }
1157
    monitor_printf(mon, "      id \"%s\"\n", d->qdev.id ? d->qdev.id : "");
1158
    if (class == 0x0604 && d->config[0x19] != 0) {
1159
        pci_for_each_device(bus, d->config[0x19], pci_info_device);
1183

  
1184
    monitor_printf(mon, "      id \"%s\"\n", qdict_get_str(device, "qdev_id"));
1185

  
1186
    /* TODO: PCI bridge devices */
1187
}
1188

  
1189
void do_pci_info_print(Monitor *mon, const QObject *data)
1190
{
1191
    QListEntry *bus, *dev;
1192

  
1193
    QLIST_FOREACH_ENTRY(qobject_to_qlist(data), bus) {
1194
        QDict *qdict = qobject_to_qdict(qlist_entry_obj(bus));
1195
        QLIST_FOREACH_ENTRY(qdict_get_qlist(qdict, "devices"), dev) {
1196
            pci_device_print(mon, qobject_to_qdict(qlist_entry_obj(dev)));
1197
        }
1160 1198
    }
1161 1199
}
1162 1200

  
1163
static void pci_for_each_device_under_bus(PCIBus *bus,
1164
                                          void (*fn)(PCIBus *b, PCIDevice *d))
1201
static QObject *pci_get_dev_class(const PCIDevice *dev)
1202
{
1203
    int class;
1204
    const pci_class_desc *desc;
1205

  
1206
    class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
1207
    desc = pci_class_descriptions;
1208
    while (desc->desc && class != desc->class)
1209
        desc++;
1210

  
1211
    if (desc->desc) {
1212
        return qobject_from_jsonf("{ 'desc': %s, 'class': %d }",
1213
                                  desc->desc, class);
1214
    } else {
1215
        return qobject_from_jsonf("{ 'class': %d }", class);
1216
    }
1217
}
1218

  
1219
static QObject *pci_get_dev_id(const PCIDevice *dev)
1220
{
1221
    return qobject_from_jsonf("{ 'device': %d, 'vendor': %d }",
1222
                              pci_get_word(dev->config + PCI_VENDOR_ID),
1223
                              pci_get_word(dev->config + PCI_DEVICE_ID));
1224
}
1225

  
1226
static QObject *pci_get_regions_list(const PCIDevice *dev)
1227
{
1228
    int i;
1229
    QList *regions_list;
1230

  
1231
    regions_list = qlist_new();
1232

  
1233
    for (i = 0; i < PCI_NUM_REGIONS; i++) {
1234
        QObject *obj;
1235
        const PCIIORegion *r = &dev->io_regions[i];
1236

  
1237
        if (!r->size) {
1238
            continue;
1239
        }
1240

  
1241
        if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
1242
            obj = qobject_from_jsonf("{ 'bar': %d, 'type': 'io', "
1243
                                     "'address': %" PRId64 ", "
1244
                                     "'size': %" PRId64 " }",
1245
                                     i, r->addr, r->size);
1246
        } else {
1247
            int mem_type_64 = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64;
1248

  
1249
            obj = qobject_from_jsonf("{ 'bar': %d, 'type': 'memory', "
1250
                                     "'mem_type_64': %i, 'prefetch': %i, "
1251
                                     "'address': %" PRId64 ", "
1252
                                     "'size': %" PRId64 " }",
1253
                                     i, mem_type_64,
1254
                                     r->type & PCI_BASE_ADDRESS_MEM_PREFETCH,
1255
                                     r->addr, r->size);
1256
        }
1257

  
1258
        qlist_append_obj(regions_list, obj);
1259
    }
1260

  
1261
    return QOBJECT(regions_list);
1262
}
1263

  
1264
static QObject *pci_get_dev_dict(PCIDevice *dev, int bus_num)
1265
{
1266
    int class;
1267
    QObject *obj;
1268

  
1269
    obj = qobject_from_jsonf("{ 'bus': %d, 'slot': %d, 'function': %d,"                                       "'class_info': %p, 'id': %p, 'regions': %p,"
1270
                              " 'qdev_id': %s }",
1271
                              bus_num,
1272
                              PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
1273
                              pci_get_dev_class(dev), pci_get_dev_id(dev),
1274
                              pci_get_regions_list(dev),
1275
                              dev->qdev.id ? dev->qdev.id : "");
1276

  
1277
    if (dev->config[PCI_INTERRUPT_PIN] != 0) {
1278
        QDict *qdict = qobject_to_qdict(obj);
1279
        qdict_put(qdict, "irq", qint_from_int(dev->config[PCI_INTERRUPT_LINE]));
1280
    }
1281

  
1282
    class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
1283
    if (class == 0x0604) {
1284
        QDict *qdict;
1285
        QObject *pci_bridge;
1286

  
1287
        pci_bridge = qobject_from_jsonf("{ 'bus': "
1288
        "{ 'number': %d, 'secondary': %d, 'subordinate': %d }, "
1289
        "'io_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "}, "
1290
        "'memory_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "}, "
1291
        "'prefetchable_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "} }",
1292
        dev->config[0x19], dev->config[PCI_SECONDARY_BUS],
1293
        dev->config[PCI_SUBORDINATE_BUS],
1294
        pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO),
1295
        pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO),
1296
        pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY),
1297
        pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY),
1298
        pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY |
1299
                               PCI_BASE_ADDRESS_MEM_PREFETCH),
1300
        pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY |
1301
                                PCI_BASE_ADDRESS_MEM_PREFETCH));
1302

  
1303
        qdict = qobject_to_qdict(obj);
1304
        qdict_put_obj(qdict, "pci_bridge", pci_bridge);
1305
    }
1306

  
1307
    return obj;
1308
}
1309

  
1310
static QObject *pci_get_devices_list(PCIBus *bus, int bus_num)
1165 1311
{
1166
    PCIDevice *d;
1167 1312
    int devfn;
1313
    PCIDevice *dev;
1314
    QList *dev_list;
1168 1315

  
1169
    for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
1170
        d = bus->devices[devfn];
1171
        if (d)
1172
            fn(bus, d);
1316
    dev_list = qlist_new();
1317

  
1318
    for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
1319
        dev = bus->devices[devfn];
1320
        if (dev) {
1321
            qlist_append_obj(dev_list, pci_get_dev_dict(dev, bus_num));
1322
        }
1173 1323
    }
1324

  
1325
    return QOBJECT(dev_list);
1174 1326
}
1175 1327

  
1176
void pci_for_each_device(PCIBus *bus, int bus_num,
1177
                         void (*fn)(PCIBus *b, PCIDevice *d))
1328
static QObject *pci_get_bus_dict(PCIBus *bus, int bus_num)
1178 1329
{
1179 1330
    bus = pci_find_bus(bus, bus_num);
1180

  
1181 1331
    if (bus) {
1182
        pci_for_each_device_under_bus(bus, fn);
1332
        return qobject_from_jsonf("{ 'bus': %d, 'devices': %p }",
1333
                                  bus_num, pci_get_devices_list(bus, bus_num));
1183 1334
    }
1335

  
1336
    return NULL;
1184 1337
}
1185 1338

  
1186
void pci_info(Monitor *mon)
1339
/**
1340
 * do_pci_info(): PCI buses and devices information
1341
 *
1342
 * The returned QObject is a QList of all buses. Each bus is
1343
 * represented by a QDict, which has a key with a QList of all
1344
 * PCI devices attached to it. Each device is represented by
1345
 * a QDict.
1346
 *
1347
 * The bus QDict contains the following:
1348
 *
1349
 * - "bus": bus number
1350
 * - "devices": a QList of QDicts, each QDict represents a PCI
1351
 *   device
1352
 *
1353
 * The PCI device QDict contains the following:
1354
 *
1355
 * - "bus": identical to the parent's bus number
1356
 * - "slot": slot number
1357
 * - "function": function number
1358
 * - "class_info": a QDict containing:
1359
 *      - "desc": device class description (optional)
1360
 *      - "class": device class number
1361
 * - "id": a QDict containing:
1362
 *      - "device": device ID
1363
 *      - "vendor": vendor ID
1364
 * - "irq": device's IRQ if assigned (optional)
1365
 * - "qdev_id": qdev id string
1366
 * - "pci_bridge": It's a QDict, only present if this device is a
1367
 *   PCI bridge, contains:
1368
 *      - "bus": bus number
1369
 *      - "secondary": secondary bus number
1370
 *      - "subordinate": subordinate bus number
1371
 *      - "io_range": a QDict with memory range information
1372
 *      - "memory_range": a QDict with memory range information
1373
 *      - "prefetchable_range": a QDict with memory range information
1374
 * - "regions": a QList of QDicts, each QDict represents a
1375
 *   memory region of this device
1376
 *
1377
 * The memory range QDict contains the following:
1378
 *
1379
 * - "base": base memory address
1380
 * - "limit": limit value
1381
 *
1382
 * The region QDict can be an I/O region or a memory region,
1383
 * an I/O region QDict contains the following:
1384
 *
1385
 * - "type": "io"
1386
 * - "bar": BAR number
1387
 * - "address": memory address
1388
 * - "size": memory size
1389
 *
1390
 * A memory region QDict contains the following:
1391
 *
1392
 * - "type": "memory"
1393
 * - "bar": BAR number
1394
 * - "address": memory address
1395
 * - "size": memory size
1396
 * - "mem_type_64": true or false
1397
 * - "prefetch": true or false
1398
 */
1399
void do_pci_info(Monitor *mon, QObject **ret_data)
1187 1400
{
1401
    QList *bus_list;
1188 1402
    struct PCIHostBus *host;
1403

  
1404
    bus_list = qlist_new();
1405

  
1189 1406
    QLIST_FOREACH(host, &host_buses, next) {
1190
        pci_for_each_device(host->bus, 0, pci_info_device);
1407
        QObject *obj = pci_get_bus_dict(host->bus, 0);
1408
        if (obj) {
1409
            qlist_append_obj(bus_list, obj);
1410
        }
1191 1411
    }
1412

  
1413
    *ret_data = QOBJECT(bus_list);
1192 1414
}
1193 1415

  
1194 1416
static const char * const pci_nic_models[] = {

Also available in: Unified diff