~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Bus/DevPCI.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
932
932
                    goto default_map;
933
933
                /* VGA: map frame buffer to default Bochs VBE address */
934
934
                pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0xE0000000);
935
 
#ifdef VBOX_WITH_EFI
936
 
                /* The following is necessary for the VGA check in
937
 
                   PciVgaMiniPortDriverBindingSupported to succeed. */
938
 
                /** @todo Seems we're missing some I/O registers or something on the VGA device... Compare real/virt hw with lspci. */
939
 
                pci_config_writew(pGlobals, uBus, uDevFn, PCI_COMMAND,
940
 
                                  pci_config_readw(pGlobals, uBus, uDevFn, PCI_COMMAND)
 
935
                /*
 
936
                 * Legacy VGA I/O ports are implicitly decoded by a VGA class device. But
 
937
                 * only the framebuffer (i.e., a memory region) is explicitly registered via
 
938
                 * pci_set_io_region_addr, so I/O decoding must be enabled manually.
 
939
                 */
 
940
                pci_config_writeb(pGlobals, uBus, uDevFn, PCI_COMMAND,
 
941
                                  pci_config_readb(pGlobals, uBus, uDevFn, PCI_COMMAND)
941
942
                                  | 1 /* Enable I/O space access. */);
942
 
#endif
943
943
                break;
944
944
            case 0x0800:
945
945
                /* PIC */
1234
1234
 * @returns VBox status code.
1235
1235
 * @param   pDevIns         Device instance of the PCI Bus.
1236
1236
 * @param   pPciDev         Pointer to PCI device.
1237
 
 * @param   pSSMHandle      The handle to save the state to.
 
1237
 * @param   pSSM            The handle to save the state to.
1238
1238
 */
1239
 
static DECLCALLBACK(int) pciGenericSaveExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle)
 
1239
static DECLCALLBACK(int) pciGenericSaveExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
1240
1240
{
1241
 
    return SSMR3PutMem(pSSMHandle, &pPciDev->config[0], sizeof(pPciDev->config));
 
1241
    return SSMR3PutMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
1242
1242
}
1243
1243
 
1244
1244
 
1248
1248
 * @returns VBox status code.
1249
1249
 * @param   pDevIns         Device instance of the PCI Bus.
1250
1250
 * @param   pPciDev         Pointer to PCI device.
1251
 
 * @param   pSSMHandle      The handle to the saved state.
1252
 
 */
1253
 
static DECLCALLBACK(int) pciGenericLoadExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle)
1254
 
{
1255
 
    return SSMR3GetMem(pSSMHandle, &pPciDev->config[0], sizeof(pPciDev->config));
 
1251
 * @param   pSSM            The handle to the saved state.
 
1252
 */
 
1253
static DECLCALLBACK(int) pciGenericLoadExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
 
1254
{
 
1255
    return SSMR3GetMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
 
1256
}
 
1257
 
 
1258
 
 
1259
/**
 
1260
 * Common worker for pciR3SaveExec and pcibridgeR3SaveExec.
 
1261
 *
 
1262
 * @returns VBox status code.
 
1263
 * @param   pBus            The bus to save.
 
1264
 * @param   pSSM            The saved state handle.
 
1265
 */
 
1266
static int pciR3CommonSaveExec(PPCIBUS pBus, PSSMHANDLE pSSM)
 
1267
{
 
1268
    /*
 
1269
     * Iterate thru all the devices.
 
1270
     */
 
1271
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
 
1272
    {
 
1273
        PPCIDEVICE pDev = pBus->devices[i];
 
1274
        if (pDev)
 
1275
        {
 
1276
            SSMR3PutU32(pSSM, i);
 
1277
            SSMR3PutMem(pSSM, pDev->config, sizeof(pDev->config));
 
1278
 
 
1279
            int rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
 
1280
            if (RT_FAILURE(rc))
 
1281
                return rc;
 
1282
        }
 
1283
    }
 
1284
    return SSMR3PutU32(pSSM, UINT32_MAX); /* terminator */
1256
1285
}
1257
1286
 
1258
1287
 
1262
1291
 * @returns VBox status code.
1263
1292
 * @param   pDevIns     The device instance.
1264
1293
 * @param   pPciDev     Pointer to PCI device.
1265
 
 * @param   pSSMHandle  The handle to save the state to.
 
1294
 * @param   pSSM  The handle to save the state to.
1266
1295
 */
1267
 
static DECLCALLBACK(int) pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
 
1296
static DECLCALLBACK(int) pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1268
1297
{
1269
1298
    uint32_t    i;
1270
1299
    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1271
 
    PPCIBUS     pBus =  &pThis->PciBus;
1272
1300
 
1273
1301
    /*
1274
1302
     * Bus state data.
1275
1303
     */
1276
 
    SSMR3PutU32(pSSMHandle, pThis->uConfigReg);
1277
 
    SSMR3PutBool(pSSMHandle, pThis->fUseIoApic);
 
1304
    SSMR3PutU32(pSSM, pThis->uConfigReg);
 
1305
    SSMR3PutBool(pSSM, pThis->fUseIoApic);
1278
1306
 
1279
1307
    /*
1280
1308
     * Save IRQ states.
1281
1309
     */
1282
1310
    for (i = 0; i < PCI_IRQ_PINS; i++)
1283
 
        SSMR3PutU32(pSSMHandle, pThis->pci_irq_levels[i]);
 
1311
        SSMR3PutU32(pSSM, pThis->pci_irq_levels[i]);
1284
1312
    for (i = 0; i < PCI_APIC_IRQ_PINS; i++)
1285
 
        SSMR3PutU32(pSSMHandle, pThis->pci_apic_irq_levels[i]);
1286
 
 
1287
 
    SSMR3PutU32(pSSMHandle, pThis->acpi_irq_level);
1288
 
    SSMR3PutS32(pSSMHandle, pThis->acpi_irq);
1289
 
 
1290
 
    SSMR3PutU32(pSSMHandle, ~0);        /* separator */
1291
 
 
1292
 
    /*
1293
 
     * Iterate thru all the devices.
1294
 
     */
1295
 
    for (i = 0; i < RT_ELEMENTS(pBus->devices); i++)
1296
 
    {
1297
 
        PPCIDEVICE pDev = pBus->devices[i];
1298
 
        if (pDev)
1299
 
        {
1300
 
            int rc;
1301
 
            SSMR3PutU32(pSSMHandle, i);
1302
 
            SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
1303
 
 
1304
 
            rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState);
1305
 
            if (RT_FAILURE(rc))
1306
 
                return rc;
1307
 
        }
1308
 
    }
1309
 
    return SSMR3PutU32(pSSMHandle, ~0); /* terminator */
1310
 
}
1311
 
 
1312
 
 
1313
 
/**
1314
 
 * Disables all PCI devices prior to state loading.
1315
 
 *
1316
 
 * @returns VINF_SUCCESS.
1317
 
 * @param   pBus                The PCI bus instance.
1318
 
 */
1319
 
static int pciR3CommonLoadPrep(PPCIBUS pBus)
1320
 
{
1321
 
    /*
1322
 
     * Iterate thru all the devices and write 0 to the COMMAND register.
1323
 
     * The register value is restored afterwards so we can do proper
1324
 
     * LogRels in pciR3CommonRestoreConfig.
1325
 
     */
1326
 
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
1327
 
    {
1328
 
        PPCIDEVICE pDev = pBus->devices[i];
1329
 
        if (pDev)
1330
 
        {
1331
 
            uint16_t u16 = PCIDevGetCommand(pDev);
1332
 
            pDev->Int.s.pfnConfigWrite(pDev, VBOX_PCI_COMMAND, 0, 2);
1333
 
            PCIDevSetCommand(pDev, u16);
1334
 
            Assert(PCIDevGetCommand(pDev) == u16);
1335
 
        }
1336
 
    }
1337
 
    return VINF_SUCCESS;
1338
 
}
1339
 
 
1340
 
 
1341
 
/**
1342
 
 * Prepares a state load.
1343
 
 *
1344
 
 * This will disable all the device so that the I/O regions gets unmapped.
1345
 
 *
1346
 
 * @returns VINF_SUCCESS
1347
 
 * @param   pDevIns             The device instance.
1348
 
 * @param   pSSMHandle          The saved state handle.
1349
 
 */
1350
 
static DECLCALLBACK(int) pciR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1351
 
{
1352
 
    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1353
 
    return pciR3CommonLoadPrep(&pThis->PciBus);
 
1313
        SSMR3PutU32(pSSM, pThis->pci_apic_irq_levels[i]);
 
1314
 
 
1315
    SSMR3PutU32(pSSM, pThis->acpi_irq_level);
 
1316
    SSMR3PutS32(pSSM, pThis->acpi_irq);
 
1317
 
 
1318
    SSMR3PutU32(pSSM, ~0);        /* separator */
 
1319
 
 
1320
    /*
 
1321
     * Join paths with pcibridgeR3SaveExec.
 
1322
     */
 
1323
    return pciR3CommonSaveExec(&pThis->PciBus, pSSM);
1354
1324
}
1355
1325
 
1356
1326
 
1498
1468
                                pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
1499
1469
                }
1500
1470
                if (off == VBOX_PCI_COMMAND)
1501
 
                    PCIDevSetCommand(pDev, 0); /* For remapping, see pciR3CommonLoadPrep. */
 
1471
                    PCIDevSetCommand(pDev, 0); /* For remapping, see pciR3CommonLoadExec. */
1502
1472
                pDev->Int.s.pfnConfigWrite(pDev, off, u32Src, cb);
1503
1473
            }
1504
1474
        }
1521
1491
 
1522
1492
 
1523
1493
/**
 
1494
 * Common worker for pciR3LoadExec and pcibridgeR3LoadExec.
 
1495
 *
 
1496
 * @returns VBox status code.
 
1497
 * @param   pBus                The bus which data is being loaded.
 
1498
 * @param   pSSM                The saved state handle.
 
1499
 * @param   uVersion            The data version.
 
1500
 * @param   uPass               The pass.
 
1501
 */
 
1502
static DECLCALLBACK(int) pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 
1503
{
 
1504
    uint32_t    u32;
 
1505
    uint32_t    i;
 
1506
    int         rc;
 
1507
 
 
1508
    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
 
1509
 
 
1510
    /*
 
1511
     * Iterate thru all the devices and write 0 to the COMMAND register so
 
1512
     * that all the memory is unmapped before we start restoring the saved
 
1513
     * mapping locations.
 
1514
     *
 
1515
     * The register value is restored afterwards so we can do proper
 
1516
     * LogRels in pciR3CommonRestoreConfig.
 
1517
     */
 
1518
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
 
1519
    {
 
1520
        PPCIDEVICE pDev = pBus->devices[i];
 
1521
        if (pDev)
 
1522
        {
 
1523
            uint16_t u16 = PCIDevGetCommand(pDev);
 
1524
            pDev->Int.s.pfnConfigWrite(pDev, VBOX_PCI_COMMAND, 0, 2);
 
1525
            PCIDevSetCommand(pDev, u16);
 
1526
            Assert(PCIDevGetCommand(pDev) == u16);
 
1527
        }
 
1528
    }
 
1529
 
 
1530
    /*
 
1531
     * Iterate all the devices.
 
1532
     */
 
1533
    for (i = 0;; i++)
 
1534
    {
 
1535
        PCIDEVICE   DevTmp;
 
1536
        PPCIDEVICE  pDev;
 
1537
 
 
1538
        /* index / terminator */
 
1539
        rc = SSMR3GetU32(pSSM, &u32);
 
1540
        if (RT_FAILURE(rc))
 
1541
            return rc;
 
1542
        if (u32 == (uint32_t)~0)
 
1543
            break;
 
1544
        if (    u32 >= RT_ELEMENTS(pBus->devices)
 
1545
            ||  u32 < i)
 
1546
        {
 
1547
            AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
 
1548
            return rc;
 
1549
        }
 
1550
 
 
1551
        /* skip forward to the device checking that no new devices are present. */
 
1552
        for (; i < u32; i++)
 
1553
        {
 
1554
            if (pBus->devices[i])
 
1555
            {
 
1556
                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name,
 
1557
                        PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i])));
 
1558
                if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
 
1559
                    return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("New device in slot %#x, %s (vendor=%#06x device=%#06x)"),
 
1560
                                            i, pBus->devices[i]->name, PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i]));
 
1561
            }
 
1562
        }
 
1563
 
 
1564
        /* get the data */
 
1565
        DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
 
1566
        SSMR3GetMem(pSSM, DevTmp.config, sizeof(DevTmp.config));
 
1567
        if (uVersion < 3)
 
1568
        {
 
1569
            int32_t i32Temp;
 
1570
            /* Irq value not needed anymore. */
 
1571
            rc = SSMR3GetS32(pSSM, &i32Temp);
 
1572
            if (RT_FAILURE(rc))
 
1573
                return rc;
 
1574
        }
 
1575
        else
 
1576
        {
 
1577
            rc = SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState);
 
1578
            if (RT_FAILURE(rc))
 
1579
                return rc;
 
1580
        }
 
1581
 
 
1582
        /* check that it's still around. */
 
1583
        pDev = pBus->devices[i];
 
1584
        if (!pDev)
 
1585
        {
 
1586
            LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
 
1587
                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
 
1588
            if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
 
1589
                return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x has been removed! vendor=%#06x device=%#06x"),
 
1590
                                        i, PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp));
 
1591
            continue;
 
1592
        }
 
1593
 
 
1594
        /* match the vendor id assuming that this will never be changed. */
 
1595
        if (    DevTmp.config[0] != pDev->config[0]
 
1596
            ||  DevTmp.config[1] != pDev->config[1])
 
1597
            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
 
1598
                                     i, pDev->name, DevTmp.config, pDev->config);
 
1599
 
 
1600
        /* commit the loaded device config. */
 
1601
        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
 
1602
 
 
1603
        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
 
1604
    }
 
1605
 
 
1606
    return VINF_SUCCESS;
 
1607
}
 
1608
 
 
1609
 
 
1610
/**
1524
1611
 * Loads a saved PCI device state.
1525
1612
 *
1526
1613
 * @returns VBox status code.
1527
1614
 * @param   pDevIns     The device instance.
1528
 
 * @param   pSSMHandle  The handle to the saved state.
1529
 
 * @param   u32Version  The data unit version number.
 
1615
 * @param   pSSM        The handle to the saved state.
 
1616
 * @param   uVersion    The data unit version number.
 
1617
 * @param   uPass       The data pass.
1530
1618
 */
1531
 
static DECLCALLBACK(int) pciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
 
1619
static DECLCALLBACK(int) pciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1532
1620
{
1533
1621
    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1534
1622
    PPCIBUS     pBus  = &pThis->PciBus;
1535
1623
    uint32_t    u32;
1536
 
    uint32_t    i;
1537
1624
    int         rc;
1538
1625
 
1539
1626
    /*
1540
1627
     * Check the version.
1541
1628
     */
1542
 
    if (u32Version > VBOX_PCI_SAVED_STATE_VERSION)
1543
 
    {
1544
 
        AssertFailed();
 
1629
    if (uVersion > VBOX_PCI_SAVED_STATE_VERSION)
1545
1630
        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1546
 
    }
 
1631
    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
1547
1632
 
1548
1633
    /*
1549
1634
     * Bus state data.
1550
1635
     */
1551
 
    SSMR3GetU32(pSSMHandle, &pThis->uConfigReg);
1552
 
    if (u32Version > 1)
1553
 
        SSMR3GetBool(pSSMHandle, &pThis->fUseIoApic);
 
1636
    SSMR3GetU32(pSSM, &pThis->uConfigReg);
 
1637
    if (uVersion > 1)
 
1638
        SSMR3GetBool(pSSM, &pThis->fUseIoApic);
1554
1639
 
1555
1640
    /* Load IRQ states. */
1556
 
    if (u32Version > 2)
 
1641
    if (uVersion > 2)
1557
1642
    {
1558
1643
        for (uint8_t i = 0; i < PCI_IRQ_PINS; i++)
1559
 
            SSMR3GetU32(pSSMHandle, (uint32_t *)&pThis->pci_irq_levels[i]);
 
1644
            SSMR3GetU32(pSSM, (uint32_t *)&pThis->pci_irq_levels[i]);
1560
1645
        for (uint8_t i = 0; i < PCI_APIC_IRQ_PINS; i++)
1561
 
            SSMR3GetU32(pSSMHandle, (uint32_t *)&pThis->pci_apic_irq_levels[i]);
 
1646
            SSMR3GetU32(pSSM, (uint32_t *)&pThis->pci_apic_irq_levels[i]);
1562
1647
 
1563
 
        SSMR3GetU32(pSSMHandle, &pThis->acpi_irq_level);
1564
 
        SSMR3GetS32(pSSMHandle, &pThis->acpi_irq);
 
1648
        SSMR3GetU32(pSSM, &pThis->acpi_irq_level);
 
1649
        SSMR3GetS32(pSSM, &pThis->acpi_irq);
1565
1650
    }
1566
1651
 
1567
1652
    /* separator */
1568
 
    rc = SSMR3GetU32(pSSMHandle, &u32);
 
1653
    rc = SSMR3GetU32(pSSM, &u32);
1569
1654
    if (RT_FAILURE(rc))
1570
1655
        return rc;
1571
1656
    if (u32 != (uint32_t)~0)
1572
1657
        AssertMsgFailedReturn(("u32=%#x\n", u32), rc);
1573
1658
 
1574
1659
    /*
1575
 
     * Iterate all the devices.
 
1660
     * The devices.
1576
1661
     */
1577
 
    for (i = 0;; i++)
1578
 
    {
1579
 
        PCIDEVICE   DevTmp;
1580
 
        PPCIDEVICE  pDev;
1581
 
 
1582
 
        /* index / terminator */
1583
 
        rc = SSMR3GetU32(pSSMHandle, &u32);
1584
 
        if (RT_FAILURE(rc))
1585
 
            return rc;
1586
 
        if (u32 == (uint32_t)~0)
1587
 
            break;
1588
 
        if (    u32 >= RT_ELEMENTS(pBus->devices)
1589
 
            ||  u32 < i)
1590
 
        {
1591
 
            AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
1592
 
            return rc;
1593
 
        }
1594
 
 
1595
 
        /* skip forward to the device checking that no new devices are present. */
1596
 
        for (; i < u32; i++)
1597
 
        {
1598
 
            if (pBus->devices[i])
1599
 
            {
1600
 
                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name,
1601
 
                        PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i])));
1602
 
                if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
1603
 
                    AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
1604
 
            }
1605
 
        }
1606
 
 
1607
 
        /* Get the data */
1608
 
        DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
1609
 
        SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config));
1610
 
        if (u32Version < 3)
1611
 
        {
1612
 
            int32_t i32Temp;
1613
 
            /* Irq value not needed anymore. */
1614
 
            rc = SSMR3GetS32(pSSMHandle, &i32Temp);
1615
 
            if (RT_FAILURE(rc))
1616
 
                return rc;
1617
 
        }
1618
 
        else
1619
 
        {
1620
 
            rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState);
1621
 
            if (RT_FAILURE(rc))
1622
 
                return rc;
1623
 
        }
1624
 
 
1625
 
        /* check that it's still around. */
1626
 
        pDev = pBus->devices[i];
1627
 
        if (!pDev)
1628
 
        {
1629
 
            LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
1630
 
                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
1631
 
            if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
1632
 
                AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
1633
 
            continue;
1634
 
        }
1635
 
 
1636
 
        /* match the vendor id assuming that this will never be changed. */
1637
 
        if (    DevTmp.config[0] != pDev->config[0]
1638
 
            ||  DevTmp.config[1] != pDev->config[1])
1639
 
        {
1640
 
            LogRel(("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs\n",
1641
 
                    i, pDev->name, DevTmp.config, pDev->config));
1642
 
            AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
1643
 
        }
1644
 
 
1645
 
        /* commit the loaded device config. */
1646
 
        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
1647
 
 
1648
 
        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
1649
 
    }
1650
 
 
1651
 
    return VINF_SUCCESS;
 
1662
    return pciR3CommonLoadExec(pBus, pSSM, uVersion, uPass);
1652
1663
}
1653
1664
 
1654
1665
 
1892
1903
 */
1893
1904
static DECLCALLBACK(int) pciFakePCIBIOS(PPDMDEVINS pDevIns)
1894
1905
{
1895
 
    int         rc;
1896
1906
    unsigned    i;
1897
1907
    uint8_t     elcr[2] = {0, 0};
1898
1908
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1919
1929
    }
1920
1930
 
1921
1931
    /* Tell to the PIC. */
1922
 
    rc = IOMIOPortWrite(pVM, 0x4d0, elcr[0], sizeof(uint8_t));
1923
 
    if (rc == VINF_SUCCESS)
1924
 
        rc = IOMIOPortWrite(pVM, 0x4d1, elcr[1], sizeof(uint8_t));
1925
 
    if (rc != VINF_SUCCESS)
 
1932
    VBOXSTRICTRC rcStrict = IOMIOPortWrite(pVM, 0x4d0, elcr[0], sizeof(uint8_t));
 
1933
    if (rcStrict == VINF_SUCCESS)
 
1934
        rcStrict = IOMIOPortWrite(pVM, 0x4d1, elcr[1], sizeof(uint8_t));
 
1935
    if (rcStrict != VINF_SUCCESS)
1926
1936
    {
1927
 
        AssertMsgFailed(("Writing to PIC failed!\n"));
1928
 
        return RT_SUCCESS(rc) ? VERR_INTERNAL_ERROR : rc;
 
1937
        AssertMsgFailed(("Writing to PIC failed! rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
 
1938
        return RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR : VBOXSTRICTRC_VAL(rcStrict);
1929
1939
    }
1930
1940
 
1931
1941
    /*
2049
2059
    if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
2050
2060
        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
2051
2061
                                   N_("PCI helper version mismatch; got %#x expected %#x"),
2052
 
                                  pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION);
 
2062
                                   pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION);
2053
2063
 
2054
2064
    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
2055
2065
    pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
2111
2121
            return rc;
2112
2122
    }
2113
2123
 
2114
 
    rc = SSMR3RegisterDevice(PDMDevHlpGetVM(pDevIns), pDevIns, "pci", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus) + 16*128, "pgm",
2115
 
                             NULL, pciR3SaveExec, NULL, pciR3LoadPrep, pciR3LoadExec, NULL);
 
2124
    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus) + 16*128, "pgm",
 
2125
                                NULL, NULL, NULL,
 
2126
                                NULL, pciR3SaveExec, NULL,
 
2127
                                NULL, pciR3LoadExec, NULL);
2116
2128
    if (RT_FAILURE(rc))
2117
2129
        return rc;
2118
2130
 
2177
2189
};
2178
2190
#endif /* IN_RING3 */
2179
2191
 
 
2192
 
2180
2193
/**
2181
2194
 * Set the IRQ for a PCI device on a secondary bus.
2182
2195
 *
2194
2207
     * We change iIrq here according to the spec and call the SetIrq function
2195
2208
     * of our parent passing the device which asserted the interrupt instead of the device of the bridge.
2196
2209
     */
2197
 
    PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
2198
 
    int iIrqPinBridge = 0;
2199
 
    uint8_t uDevFnBridge = pPciDev->devfn;
 
2210
    PPCIBUS    pBus          = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
2211
    PPCIDEVICE pPciDevBus    = pPciDev;
 
2212
    int        iIrqPinBridge = iIrq;
 
2213
    uint8_t    uDevFnBridge  = 0;
2200
2214
 
2201
2215
    /* Walk the chain until we reach the host bus. */
2202
 
    while (pBus->iBus != 0)
 
2216
    do
2203
2217
    {
2204
 
        uDevFnBridge = pBus->PciDev.devfn;
2205
 
        iIrqPinBridge = ((uDevFnBridge >> 3) + iIrqPinBridge) & 3;
 
2218
        uDevFnBridge  = pBus->PciDev.devfn;
 
2219
        iIrqPinBridge = ((pPciDevBus->devfn >> 3) + iIrqPinBridge) & 3;
 
2220
 
2206
2221
        /* Get the parent. */
2207
2222
        pBus = pBus->PciDev.Int.s.CTX_SUFF(pBus);
2208
 
    }
 
2223
        pPciDevBus = &pBus->PciDev;
 
2224
    } while (pBus->iBus != 0);
2209
2225
 
2210
2226
    AssertMsg(pBus->iBus == 0, ("This is not the host pci bus iBus=%d\n", pBus->iBus));
2211
2227
    pciSetIrqInternal(PCIBUS_2_PCIGLOBALS(pBus), uDevFnBridge, pPciDev, iIrqPinBridge, iLevel);
2272
2288
    return u32Value;
2273
2289
}
2274
2290
 
2275
 
/**
2276
 
 * Saves a state of a PCI bridge device.
2277
 
 *
2278
 
 * @returns VBox status code.
2279
 
 * @param   pDevIns     The device instance.
2280
 
 * @param   pPciDev     Pointer to PCI device.
2281
 
 * @param   pSSMHandle  The handle to save the state to.
2282
 
 */
2283
 
static DECLCALLBACK(int) pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2284
 
{
2285
 
/** @todo make common with pciR3SaveExec! */
2286
 
    uint32_t    i;
2287
 
    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
2288
 
 
2289
 
    /*
2290
 
     * Iterate all the devices.
2291
 
     */
2292
 
    for (i = 0; i < RT_ELEMENTS(pThis->devices); i++)
2293
 
    {
2294
 
        PPCIDEVICE pDev = pThis->devices[i];
2295
 
        if (pDev)
2296
 
        {
2297
 
            int rc;
2298
 
            SSMR3PutU32(pSSMHandle, i);
2299
 
            SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
2300
 
 
2301
 
            rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState);
2302
 
            if (RT_FAILURE(rc))
2303
 
                return rc;
2304
 
        }
2305
 
    }
2306
 
    return SSMR3PutU32(pSSMHandle, ~0); /* terminator */
2307
 
}
2308
 
 
2309
 
 
2310
 
/**
2311
 
 * Prepares a state load.
2312
 
 *
2313
 
 * This will disable all the device so that the I/O regions gets unmapped.
2314
 
 *
2315
 
 * @returns VINF_SUCCESS
2316
 
 * @param   pDevIns             The device instance.
2317
 
 * @param   pSSMHandle          The saved state handle.
2318
 
 */
2319
 
static DECLCALLBACK(int) pcibridgeR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2320
 
{
2321
 
    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
2322
 
    return pciR3CommonLoadPrep(pThis);
2323
 
}
2324
 
 
2325
 
 
2326
 
/**
2327
 
 * Loads a saved PCI bridge device state.
2328
 
 *
2329
 
 * @returns VBox status code.
2330
 
 * @param   pDevIns     The device instance.
2331
 
 * @param   pSSMHandle  The handle to the saved state.
2332
 
 * @param   u32Version  The data unit version number.
2333
 
 */
2334
 
static DECLCALLBACK(int) pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
2335
 
{
2336
 
    PPCIBUS     pBus  = PDMINS_2_DATA(pDevIns, PPCIBUS);
2337
 
    uint32_t    u32;
2338
 
    uint32_t    i;
2339
 
    int         rc;
2340
 
 
2341
 
/** @todo r=bird: this is a copy of pciR3LoadExec. combine the two!  */
2342
 
 
2343
 
    /*
2344
 
     * Check the version.
2345
 
     */
2346
 
    if (u32Version > VBOX_PCI_SAVED_STATE_VERSION)
2347
 
    {
2348
 
        AssertFailed();
 
2291
 
 
2292
/**
 
2293
 * @copydoc FNSSMDEVSAVEEXEC
 
2294
 */
 
2295
static DECLCALLBACK(int) pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 
2296
{
 
2297
    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
2298
    return pciR3CommonSaveExec(pThis, pSSM);
 
2299
}
 
2300
 
 
2301
 
 
2302
/**
 
2303
 * @copydoc FNSSMDEVLOADEXEC
 
2304
 */
 
2305
static DECLCALLBACK(int) pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 
2306
{
 
2307
    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
2308
    if (uVersion > VBOX_PCI_SAVED_STATE_VERSION)
2349
2309
        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
2350
 
    }
 
2310
    return pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
 
2311
}
 
2312
 
 
2313
 
 
2314
/**
 
2315
 * Registers the device with the default PCI bus.
 
2316
 *
 
2317
 * @returns VBox status code.
 
2318
 * @param   pDevIns         Device instance of the PCI Bus.
 
2319
 * @param   pPciDev         The PCI device structure.
 
2320
 *                          Any PCI enabled device must keep this in it's instance data!
 
2321
 *                          Fill in the PCI data config before registration, please.
 
2322
 * @param   pszName         Pointer to device name (permanent, readonly). For debugging, not unique.
 
2323
 * @param   iDev            The PCI device number. Use a negative value for auto assigning one.
 
2324
 */
 
2325
static DECLCALLBACK(int) pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
 
2326
{
 
2327
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
2351
2328
 
2352
2329
    /*
2353
 
     * Iterate all the devices.
 
2330
     * Check input.
2354
2331
     */
2355
 
    for (i = 0;; i++)
 
2332
    if (    !pszName
 
2333
        ||  !pPciDev
 
2334
        ||  iDev >= (int)RT_ELEMENTS(pBus->devices))
2356
2335
    {
2357
 
        PCIDEVICE   DevTmp;
2358
 
        PPCIDEVICE  pDev;
2359
 
 
2360
 
        /* index / terminator */
2361
 
        rc = SSMR3GetU32(pSSMHandle, &u32);
2362
 
        if (RT_FAILURE(rc))
2363
 
            return rc;
2364
 
        if (u32 == (uint32_t)~0)
2365
 
            break;
2366
 
        if (    u32 >= RT_ELEMENTS(pBus->devices)
2367
 
            ||  u32 < i)
2368
 
        {
2369
 
            AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
2370
 
            return rc;
2371
 
        }
2372
 
 
2373
 
        /* skip forward to the device checking that no new devices are present. */
2374
 
        for (; i < u32; i++)
2375
 
        {
2376
 
            if (pBus->devices[i])
2377
 
            {
2378
 
                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name,
2379
 
                        PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i])));
2380
 
                if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
2381
 
                    AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
2382
 
            }
2383
 
        }
2384
 
 
2385
 
        /* get the data */
2386
 
        DevTmp.Int.s.uIrqPinState = 0;
2387
 
        SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config));
2388
 
        rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState);
2389
 
        if (RT_FAILURE(rc))
2390
 
            return rc;
2391
 
 
2392
 
        /* check that it's still around. */
2393
 
        pDev = pBus->devices[i];
2394
 
        if (!pDev)
2395
 
        {
2396
 
            LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
2397
 
                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
2398
 
            if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
2399
 
                AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
2400
 
            continue;
2401
 
        }
2402
 
 
2403
 
        /* match the vendor id assuming that this will never be changed. */
2404
 
        if (    DevTmp.config[0] != pDev->config[0]
2405
 
            ||  DevTmp.config[1] != pDev->config[1])
2406
 
        {
2407
 
            LogRel(("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs\n",
2408
 
                    i, pDev->name, DevTmp.config, pDev->config));
2409
 
            AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
2410
 
        }
2411
 
 
2412
 
        /* commit the loaded device config. */
2413
 
        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
2414
 
 
2415
 
        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
 
2336
        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
 
2337
        return VERR_INVALID_PARAMETER;
2416
2338
    }
2417
2339
 
2418
 
    return VINF_SUCCESS;
 
2340
    /*
 
2341
     * Register the device.
 
2342
     */
 
2343
    return pciRegisterInternal(pBus, iDev, pPciDev, pszName);
2419
2344
}
2420
2345
 
 
2346
 
2421
2347
/**
2422
2348
 * @copydoc FNPDMDEVRESET
2423
2349
 */
2431
2357
    pBus->PciDev.config[VBOX_PCI_SUBORDINATE_BUS] = 0;
2432
2358
}
2433
2359
 
 
2360
 
2434
2361
/**
2435
2362
 * @copydoc FNPDMDEVRELOCATE
2436
2363
 */
2447
2374
    }
2448
2375
}
2449
2376
 
2450
 
/**
2451
 
 * Registers the device with the default PCI bus.
2452
 
 *
2453
 
 * @returns VBox status code.
2454
 
 * @param   pDevIns         Device instance of the PCI Bus.
2455
 
 * @param   pPciDev         The PCI device structure.
2456
 
 *                          Any PCI enabled device must keep this in it's instance data!
2457
 
 *                          Fill in the PCI data config before registration, please.
2458
 
 * @param   pszName         Pointer to device name (permanent, readonly). For debugging, not unique.
2459
 
 * @param   iDev            The PCI device number. Use a negative value for auto assigning one.
2460
 
 */
2461
 
static DECLCALLBACK(int) pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
2462
 
{
2463
 
    PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
2464
 
 
2465
 
    /*
2466
 
     * Check input.
2467
 
     */
2468
 
    if (    !pszName
2469
 
        ||  !pPciDev
2470
 
        ||  iDev >= (int)RT_ELEMENTS(pBus->devices))
2471
 
    {
2472
 
        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
2473
 
        return VERR_INVALID_PARAMETER;
2474
 
    }
2475
 
 
2476
 
    /*
2477
 
     * Register the device.
2478
 
     */
2479
 
    return pciRegisterInternal(pBus, iDev, pPciDev, pszName);
2480
 
}
2481
2377
 
2482
2378
/**
2483
2379
 * Construct a PCI bridge device instance for a VM.
2596
2492
     * Register SSM handlers. We use the same saved state version as for the host bridge
2597
2493
     * to make changes easier.
2598
2494
     */
2599
 
    rc = SSMR3RegisterDevice(PDMDevHlpGetVM(pDevIns), pDevIns, "pcibridge", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus) + 16*128, "pgm",
2600
 
                             NULL, pcibridgeR3SaveExec, NULL, pcibridgeR3LoadPrep, pcibridgeR3LoadExec, NULL);
 
2495
    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus) + 16*128, "pgm",
 
2496
                                NULL, NULL, NULL,
 
2497
                                NULL, pcibridgeR3SaveExec, NULL,
 
2498
                                NULL, pcibridgeR3LoadExec, NULL);
2601
2499
    if (RT_FAILURE(rc))
2602
2500
        return rc;
2603
2501
 
2604
2502
    return VINF_SUCCESS;
2605
2503
}
2606
2504
 
 
2505
 
2607
2506
/**
2608
2507
 * The device registration structure
2609
2508
 * for the PCI-to-PCI bridge.