Changeset 32557 in vbox
- Timestamp:
- Sep 16, 2010 12:35:25 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 65948
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
r32491 r32557 733 733 if (pDev) 734 734 { 735 /* Device position */ 735 736 SSMR3PutU32(pSSM, i); 737 /* PCI config registers */ 736 738 SSMR3PutMem(pSSM, pDev->config, sizeof(pDev->config)); 737 739 740 /* IRQ pin state */ 738 741 int rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState); 739 742 if (RT_FAILURE(rc)) … … 757 760 } 758 761 762 763 /** 764 * Common routine for restoring the config registers of a PCI device. 765 * 766 * @param pDev The PCI device. 767 * @param pbSrcConfig The configuration register values to be loaded. 768 * @param fIsBridge Whether this is a bridge device or not. 769 */ 770 static void pciR3CommonRestoreConfig(PPCIDEVICE pDev, uint8_t const *pbSrcConfig, bool fIsBridge) 771 { 772 /* 773 * This table defines the fields for normal devices and bridge devices, and 774 * the order in which they need to be restored. 775 */ 776 static const struct PciField 777 { 778 uint8_t off; 779 uint8_t cb; 780 uint8_t fWritable; 781 uint8_t fBridge; 782 const char *pszName; 783 } s_aFields[] = 784 { 785 /* off,cb,fW,fB, pszName */ 786 { VBOX_PCI_VENDOR_ID, 2, 0, 3, "VENDOR_ID" }, 787 { VBOX_PCI_DEVICE_ID, 2, 0, 3, "DEVICE_ID" }, 788 { VBOX_PCI_STATUS, 2, 1, 3, "STATUS" }, 789 { VBOX_PCI_REVISION_ID, 1, 0, 3, "REVISION_ID" }, 790 { VBOX_PCI_CLASS_PROG, 1, 0, 3, "CLASS_PROG" }, 791 { VBOX_PCI_CLASS_SUB, 1, 0, 3, "CLASS_SUB" }, 792 { VBOX_PCI_CLASS_DEVICE, 1, 0, 3, "CLASS_BASE" }, 793 { VBOX_PCI_CACHE_LINE_SIZE, 1, 1, 3, "CACHE_LINE_SIZE" }, 794 { VBOX_PCI_LATENCY_TIMER, 1, 1, 3, "LATENCY_TIMER" }, 795 { VBOX_PCI_HEADER_TYPE, 1, 0, 3, "HEADER_TYPE" }, 796 { VBOX_PCI_BIST, 1, 1, 3, "BIST" }, 797 { VBOX_PCI_BASE_ADDRESS_0, 4, 1, 3, "BASE_ADDRESS_0" }, 798 { VBOX_PCI_BASE_ADDRESS_1, 4, 1, 3, "BASE_ADDRESS_1" }, 799 { VBOX_PCI_BASE_ADDRESS_2, 4, 1, 1, "BASE_ADDRESS_2" }, 800 { VBOX_PCI_PRIMARY_BUS, 1, 1, 2, "PRIMARY_BUS" }, // fWritable = ?? 801 { VBOX_PCI_SECONDARY_BUS, 1, 1, 2, "SECONDARY_BUS" }, // fWritable = ?? 802 { VBOX_PCI_SUBORDINATE_BUS, 1, 1, 2, "SUBORDINATE_BUS" }, // fWritable = ?? 803 { VBOX_PCI_SEC_LATENCY_TIMER, 1, 1, 2, "SEC_LATENCY_TIMER" }, // fWritable = ?? 804 { VBOX_PCI_BASE_ADDRESS_3, 4, 1, 1, "BASE_ADDRESS_3" }, 805 { VBOX_PCI_IO_BASE, 1, 1, 2, "IO_BASE" }, // fWritable = ?? 806 { VBOX_PCI_IO_LIMIT, 1, 1, 2, "IO_LIMIT" }, // fWritable = ?? 807 { VBOX_PCI_SEC_STATUS, 2, 1, 2, "SEC_STATUS" }, // fWritable = ?? 808 { VBOX_PCI_BASE_ADDRESS_4, 4, 1, 1, "BASE_ADDRESS_4" }, 809 { VBOX_PCI_MEMORY_BASE, 2, 1, 2, "MEMORY_BASE" }, // fWritable = ?? 810 { VBOX_PCI_MEMORY_LIMIT, 2, 1, 2, "MEMORY_LIMIT" }, // fWritable = ?? 811 { VBOX_PCI_BASE_ADDRESS_4, 4, 1, 1, "BASE_ADDRESS_4" }, 812 { VBOX_PCI_PREF_MEMORY_BASE, 2, 1, 2, "PREF_MEMORY_BASE" }, // fWritable = ?? 813 { VBOX_PCI_PREF_MEMORY_LIMIT, 2, 1, 2, "PREF_MEMORY_LIMIT" }, // fWritable = ?? 814 { VBOX_PCI_CARDBUS_CIS, 4, 1, 1, "CARDBUS_CIS" }, // fWritable = ?? 815 { VBOX_PCI_PREF_BASE_UPPER32, 4, 1, 2, "PREF_BASE_UPPER32" }, // fWritable = ?? 816 { VBOX_PCI_SUBSYSTEM_VENDOR_ID, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },// fWritable = !? 817 { VBOX_PCI_PREF_LIMIT_UPPER32, 4, 1, 2, "PREF_LIMIT_UPPER32" },// fWritable = ?? 818 { VBOX_PCI_SUBSYSTEM_ID, 2, 0, 1, "SUBSYSTEM_ID" }, // fWritable = !? 819 { VBOX_PCI_ROM_ADDRESS, 4, 1, 1, "ROM_ADDRESS" }, // fWritable = ?! 820 { VBOX_PCI_IO_BASE_UPPER16, 2, 1, 2, "IO_BASE_UPPER16" }, // fWritable = ?! 821 { VBOX_PCI_IO_LIMIT_UPPER16, 2, 1, 2, "IO_LIMIT_UPPER16" }, // fWritable = ?! 822 { VBOX_PCI_CAPABILITY_LIST, 4, 0, 3, "CAPABILITY_LIST" }, // fWritable = !? cb=!? 823 { VBOX_PCI_RESERVED_38, 4, 1, 1, "RESERVED_38" }, // ??? 824 { VBOX_PCI_ROM_ADDRESS_BR, 4, 1, 2, "ROM_ADDRESS_BR" }, // fWritable = !? cb=!? fBridge=!? 825 { VBOX_PCI_INTERRUPT_LINE, 1, 1, 3, "INTERRUPT_LINE" }, // fBridge=?? 826 { VBOX_PCI_INTERRUPT_PIN, 1, 0, 3, "INTERRUPT_PIN" }, // fBridge=?? 827 { VBOX_PCI_MIN_GNT, 1, 0, 1, "MIN_GNT" }, 828 { VBOX_PCI_BRIDGE_CONTROL, 2, 1, 2, "BRIDGE_CONTROL" }, // fWritable = !? 829 { VBOX_PCI_MAX_LAT, 1, 0, 3, "MAX_LAT" }, // fBridge=!? 830 /* The COMMAND register must come last as it requires the *ADDRESS* 831 registers to be restored before we pretent to change it from 0 to 832 whatever value the guest assigned it. */ 833 { VBOX_PCI_COMMAND, 2, 1, 3, "COMMAND" }, 834 }; 835 836 #ifdef RT_STRICT 837 /* Check that we've got full register coverage. */ 838 uint32_t bmDevice[0x40 / 32]; 839 uint32_t bmBridge[0x40 / 32]; 840 RT_ZERO(bmDevice); 841 RT_ZERO(bmBridge); 842 for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++) 843 { 844 uint8_t off = s_aFields[i].off; 845 uint8_t cb = s_aFields[i].cb; 846 uint8_t f = s_aFields[i].fBridge; 847 while (cb-- > 0) 848 { 849 if (f & 1) AssertMsg(!ASMBitTest(bmDevice, off), ("%#x\n", off)); 850 if (f & 2) AssertMsg(!ASMBitTest(bmBridge, off), ("%#x\n", off)); 851 if (f & 1) ASMBitSet(bmDevice, off); 852 if (f & 2) ASMBitSet(bmBridge, off); 853 off++; 854 } 855 } 856 for (uint32_t off = 0; off < 0x40; off++) 857 { 858 AssertMsg(ASMBitTest(bmDevice, off), ("%#x\n", off)); 859 AssertMsg(ASMBitTest(bmBridge, off), ("%#x\n", off)); 860 } 861 #endif 862 863 /* 864 * Loop thru the fields covering the 64 bytes of standard registers. 865 */ 866 uint8_t const fBridge = fIsBridge ? 2 : 1; 867 uint8_t *pbDstConfig = &pDev->config[0]; 868 for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++) 869 if (s_aFields[i].fBridge & fBridge) 870 { 871 uint8_t const off = s_aFields[i].off; 872 uint8_t const cb = s_aFields[i].cb; 873 uint32_t u32Src; 874 uint32_t u32Dst; 875 switch (cb) 876 { 877 case 1: 878 u32Src = pbSrcConfig[off]; 879 u32Dst = pbDstConfig[off]; 880 break; 881 case 2: 882 u32Src = *(uint16_t const *)&pbSrcConfig[off]; 883 u32Dst = *(uint16_t const *)&pbDstConfig[off]; 884 break; 885 case 4: 886 u32Src = *(uint32_t const *)&pbSrcConfig[off]; 887 u32Dst = *(uint32_t const *)&pbDstConfig[off]; 888 break; 889 default: 890 AssertFailed(); 891 continue; 892 } 893 894 if ( u32Src != u32Dst 895 || off == VBOX_PCI_COMMAND) 896 { 897 if (u32Src != u32Dst) 898 { 899 if (!s_aFields[i].fWritable) 900 LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x - !READ ONLY!\n", 901 pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src)); 902 else 903 LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x\n", 904 pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src)); 905 } 906 if (off == VBOX_PCI_COMMAND) 907 PCIDevSetCommand(pDev, 0); /* For remapping, see pciR3CommonLoadExec. */ 908 pDev->Int.s.pfnConfigWrite(pDev, off, u32Src, cb); 909 } 910 } 911 912 /* 913 * The device dependent registers. 914 * 915 * We will not use ConfigWrite here as we have no clue about the size 916 * of the registers, so the device is responsible for correctly 917 * restoring functionality governed by these registers. 918 */ 919 for (uint32_t off = 0x40; off < sizeof(pDev->config); off++) 920 if (pbDstConfig[off] != pbSrcConfig[off]) 921 { 922 LogRel(("PCI: %8s/%u: register %02x: %02x -> %02x\n", 923 pDev->name, pDev->pDevIns->iInstance, off, pbDstConfig[off], pbSrcConfig[off])); /** @todo make this Log() later. */ 924 pbDstConfig[off] = pbSrcConfig[off]; 925 } 926 } 927 928 /** 929 * Common worker for pciR3LoadExec and pcibridgeR3LoadExec. 930 * 931 * @returns VBox status code. 932 * @param pBus The bus which data is being loaded. 933 * @param pSSM The saved state handle. 934 * @param uVersion The data version. 935 * @param uPass The pass. 936 */ 759 937 static DECLCALLBACK(int) pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 760 938 { 761 return 0; 939 uint32_t u32; 940 uint32_t i; 941 int rc; 942 943 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 944 945 /* 946 * Iterate thru all the devices and write 0 to the COMMAND register so 947 * that all the memory is unmapped before we start restoring the saved 948 * mapping locations. 949 * 950 * The register value is restored afterwards so we can do proper 951 * LogRels in pciR3CommonRestoreConfig. 952 */ 953 for (i = 0; i < RT_ELEMENTS(pBus->apDevices); i++) 954 { 955 PPCIDEVICE pDev = pBus->apDevices[i]; 956 if (pDev) 957 { 958 uint16_t u16 = PCIDevGetCommand(pDev); 959 pDev->Int.s.pfnConfigWrite(pDev, VBOX_PCI_COMMAND, 0, 2); 960 PCIDevSetCommand(pDev, u16); 961 Assert(PCIDevGetCommand(pDev) == u16); 962 } 963 } 964 965 /* 966 * Iterate all the devices. 967 */ 968 for (i = 0;; i++) 969 { 970 PCIDEVICE DevTmp; 971 PPCIDEVICE pDev; 972 973 /* index / terminator */ 974 rc = SSMR3GetU32(pSSM, &u32); 975 if (RT_FAILURE(rc)) 976 return rc; 977 if (u32 == (uint32_t)~0) 978 break; 979 if ( u32 >= RT_ELEMENTS(pBus->apDevices) 980 || u32 < i) 981 { 982 AssertMsgFailed(("u32=%#x i=%#x\n", u32, i)); 983 return rc; 984 } 985 986 /* skip forward to the device checking that no new devices are present. */ 987 for (; i < u32; i++) 988 { 989 pDev = pBus->apDevices[i]; 990 if (pDev) 991 { 992 LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pDev->name, 993 PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev))); 994 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT) 995 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("New device in slot %#x, %s (vendor=%#06x device=%#06x)"), 996 i, pDev->name, PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev)); 997 } 998 } 999 1000 /* get the data */ 1001 DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */ 1002 SSMR3GetMem(pSSM, DevTmp.config, sizeof(DevTmp.config)); 1003 1004 rc = SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState); 1005 if (RT_FAILURE(rc)) 1006 return rc; 1007 1008 /* check that it's still around. */ 1009 pDev = pBus->apDevices[i]; 1010 if (!pDev) 1011 { 1012 LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i, 1013 PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp))); 1014 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT) 1015 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x has been removed! vendor=%#06x device=%#06x"), 1016 i, PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)); 1017 continue; 1018 } 1019 1020 /* match the vendor id assuming that this will never be changed. */ 1021 if ( DevTmp.config[0] != pDev->config[0] 1022 || DevTmp.config[1] != pDev->config[1]) 1023 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"), 1024 i, pDev->name, DevTmp.config, pDev->config); 1025 1026 /* commit the loaded device config. */ 1027 pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */ 1028 1029 pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState; 1030 } 1031 1032 return VINF_SUCCESS; 762 1033 } 763 1034
Note:
See TracChangeset
for help on using the changeset viewer.