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.
1267
static DECLCALLBACK(int) pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1296
static DECLCALLBACK(int) pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1270
1299
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1271
PPCIBUS pBus = &pThis->PciBus;
1274
1302
* Bus state data.
1276
SSMR3PutU32(pSSMHandle, pThis->uConfigReg);
1277
SSMR3PutBool(pSSMHandle, pThis->fUseIoApic);
1304
SSMR3PutU32(pSSM, pThis->uConfigReg);
1305
SSMR3PutBool(pSSM, pThis->fUseIoApic);
1280
1308
* Save IRQ states.
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]);
1287
SSMR3PutU32(pSSMHandle, pThis->acpi_irq_level);
1288
SSMR3PutS32(pSSMHandle, pThis->acpi_irq);
1290
SSMR3PutU32(pSSMHandle, ~0); /* separator */
1293
* Iterate thru all the devices.
1295
for (i = 0; i < RT_ELEMENTS(pBus->devices); i++)
1297
PPCIDEVICE pDev = pBus->devices[i];
1301
SSMR3PutU32(pSSMHandle, i);
1302
SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
1304
rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState);
1309
return SSMR3PutU32(pSSMHandle, ~0); /* terminator */
1314
* Disables all PCI devices prior to state loading.
1316
* @returns VINF_SUCCESS.
1317
* @param pBus The PCI bus instance.
1319
static int pciR3CommonLoadPrep(PPCIBUS pBus)
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.
1326
for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
1328
PPCIDEVICE pDev = pBus->devices[i];
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);
1337
return VINF_SUCCESS;
1342
* Prepares a state load.
1344
* This will disable all the device so that the I/O regions gets unmapped.
1346
* @returns VINF_SUCCESS
1347
* @param pDevIns The device instance.
1348
* @param pSSMHandle The saved state handle.
1350
static DECLCALLBACK(int) pciR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1352
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1353
return pciR3CommonLoadPrep(&pThis->PciBus);
1313
SSMR3PutU32(pSSM, pThis->pci_apic_irq_levels[i]);
1315
SSMR3PutU32(pSSM, pThis->acpi_irq_level);
1316
SSMR3PutS32(pSSM, pThis->acpi_irq);
1318
SSMR3PutU32(pSSM, ~0); /* separator */
1321
* Join paths with pcibridgeR3SaveExec.
1323
return pciR3CommonSaveExec(&pThis->PciBus, pSSM);
1494
* Common worker for pciR3LoadExec and pcibridgeR3LoadExec.
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.
1502
static DECLCALLBACK(int) pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1508
Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
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.
1515
* The register value is restored afterwards so we can do proper
1516
* LogRels in pciR3CommonRestoreConfig.
1518
for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
1520
PPCIDEVICE pDev = pBus->devices[i];
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);
1531
* Iterate all the devices.
1538
/* index / terminator */
1539
rc = SSMR3GetU32(pSSM, &u32);
1542
if (u32 == (uint32_t)~0)
1544
if ( u32 >= RT_ELEMENTS(pBus->devices)
1547
AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
1551
/* skip forward to the device checking that no new devices are present. */
1552
for (; i < u32; i++)
1554
if (pBus->devices[i])
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]));
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));
1570
/* Irq value not needed anymore. */
1571
rc = SSMR3GetS32(pSSM, &i32Temp);
1577
rc = SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState);
1582
/* check that it's still around. */
1583
pDev = pBus->devices[i];
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));
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);
1600
/* commit the loaded device config. */
1601
pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
1603
pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
1606
return VINF_SUCCESS;
1524
1611
* Loads a saved PCI device state.
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.
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)
1533
1621
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1534
1622
PPCIBUS pBus = &pThis->PciBus;
1540
1627
* Check the version.
1542
if (u32Version > VBOX_PCI_SAVED_STATE_VERSION)
1629
if (uVersion > VBOX_PCI_SAVED_STATE_VERSION)
1545
1630
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1631
Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
1549
1634
* Bus state data.
1551
SSMR3GetU32(pSSMHandle, &pThis->uConfigReg);
1553
SSMR3GetBool(pSSMHandle, &pThis->fUseIoApic);
1636
SSMR3GetU32(pSSM, &pThis->uConfigReg);
1638
SSMR3GetBool(pSSM, &pThis->fUseIoApic);
1555
1640
/* Load IRQ states. */
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]);
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);
1567
1652
/* separator */
1568
rc = SSMR3GetU32(pSSMHandle, &u32);
1653
rc = SSMR3GetU32(pSSM, &u32);
1569
1654
if (RT_FAILURE(rc))
1571
1656
if (u32 != (uint32_t)~0)
1572
1657
AssertMsgFailedReturn(("u32=%#x\n", u32), rc);
1575
* Iterate all the devices.
1582
/* index / terminator */
1583
rc = SSMR3GetU32(pSSMHandle, &u32);
1586
if (u32 == (uint32_t)~0)
1588
if ( u32 >= RT_ELEMENTS(pBus->devices)
1591
AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
1595
/* skip forward to the device checking that no new devices are present. */
1596
for (; i < u32; i++)
1598
if (pBus->devices[i])
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);
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));
1613
/* Irq value not needed anymore. */
1614
rc = SSMR3GetS32(pSSMHandle, &i32Temp);
1620
rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState);
1625
/* check that it's still around. */
1626
pDev = pBus->devices[i];
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);
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])
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);
1645
/* commit the loaded device config. */
1646
pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
1648
pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
1651
return VINF_SUCCESS;
1662
return pciR3CommonLoadExec(pBus, pSSM, uVersion, uPass);
2272
2288
return u32Value;
2276
* Saves a state of a PCI bridge device.
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.
2283
static DECLCALLBACK(int) pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2285
/** @todo make common with pciR3SaveExec! */
2287
PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
2290
* Iterate all the devices.
2292
for (i = 0; i < RT_ELEMENTS(pThis->devices); i++)
2294
PPCIDEVICE pDev = pThis->devices[i];
2298
SSMR3PutU32(pSSMHandle, i);
2299
SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
2301
rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState);
2306
return SSMR3PutU32(pSSMHandle, ~0); /* terminator */
2311
* Prepares a state load.
2313
* This will disable all the device so that the I/O regions gets unmapped.
2315
* @returns VINF_SUCCESS
2316
* @param pDevIns The device instance.
2317
* @param pSSMHandle The saved state handle.
2319
static DECLCALLBACK(int) pcibridgeR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2321
PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
2322
return pciR3CommonLoadPrep(pThis);
2327
* Loads a saved PCI bridge device state.
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.
2334
static DECLCALLBACK(int) pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
2336
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
2341
/** @todo r=bird: this is a copy of pciR3LoadExec. combine the two! */
2344
* Check the version.
2346
if (u32Version > VBOX_PCI_SAVED_STATE_VERSION)
2293
* @copydoc FNSSMDEVSAVEEXEC
2295
static DECLCALLBACK(int) pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
2297
PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
2298
return pciR3CommonSaveExec(pThis, pSSM);
2303
* @copydoc FNSSMDEVLOADEXEC
2305
static DECLCALLBACK(int) pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
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;
2310
return pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
2315
* Registers the device with the default PCI bus.
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.
2325
static DECLCALLBACK(int) pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
2327
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
2353
* Iterate all the devices.
2334
|| iDev >= (int)RT_ELEMENTS(pBus->devices))
2360
/* index / terminator */
2361
rc = SSMR3GetU32(pSSMHandle, &u32);
2364
if (u32 == (uint32_t)~0)
2366
if ( u32 >= RT_ELEMENTS(pBus->devices)
2369
AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
2373
/* skip forward to the device checking that no new devices are present. */
2374
for (; i < u32; i++)
2376
if (pBus->devices[i])
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);
2386
DevTmp.Int.s.uIrqPinState = 0;
2387
SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config));
2388
rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState);
2392
/* check that it's still around. */
2393
pDev = pBus->devices[i];
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);
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])
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);
2412
/* commit the loaded device config. */
2413
pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
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;
2418
return VINF_SUCCESS;
2341
* Register the device.
2343
return pciRegisterInternal(pBus, iDev, pPciDev, pszName);
2422
2348
* @copydoc FNPDMDEVRESET