Changeset 64457 in vbox for trunk/src/VBox
- Timestamp:
- Oct 28, 2016 1:51:57 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
r64456 r64457 732 732 DECLINLINE(uint32_t) ich9pciGetRegionReg(int iRegion) 733 733 { 734 return (iRegion == VBOX_PCI_ROM_SLOT) ?735 734 return iRegion == VBOX_PCI_ROM_SLOT 735 ? VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4); 736 736 } 737 737 … … 1931 1931 1932 1932 1933 DECLINLINE(void) ich9pciWriteBarByte(PPDMPCIDEV pPciDev, int iRegion, int iOffset, uint8_t u8Val) 1934 { 1935 PCIIORegion * pRegion = &pPciDev->Int.s.aIORegions[iRegion]; 1936 int64_t iRegionSize = pRegion->size; 1937 1938 Log3(("ich9pciWriteBarByte: region=%d off=%d val=%x size=%d\n", 1939 iRegion, iOffset, u8Val, iRegionSize)); 1940 1941 if (iOffset > 3) 1942 Assert((pRegion->type & PCI_ADDRESS_SPACE_BAR64) != 0); 1933 DECLINLINE(void) ich9pciWriteBarByte(PPDMPCIDEV pPciDev, uint32_t iRegion, uint32_t off, uint8_t bVal) 1934 { 1935 PCIIORegion *pRegion = &pPciDev->Int.s.aIORegions[iRegion]; 1936 Log3(("ich9pciWriteBarByte: region=%d off=%d val=%#x size=%#llx\n", iRegion, off, bVal, pRegion->size)); 1943 1937 1944 1938 /* Check if we're writing to upper part of 64-bit BAR. */ 1945 1939 if (pRegion->type == 0xff) 1946 { 1947 ich9pciWriteBarByte(pPciDev, iRegion-1, iOffset+4, u8Val); 1948 return; 1949 } 1950 1951 /* Region doesn't exist */ 1952 if (iRegionSize == 0) 1953 return; 1954 1955 uint32_t uAddr = ich9pciGetRegionReg(iRegion) + iOffset; 1956 /* Region size must be power of two */ 1957 Assert((iRegionSize & (iRegionSize - 1)) == 0); 1958 uint8_t uMask = ((iRegionSize - 1) >> (iOffset*8) ) & 0xff; 1959 1960 if (iOffset == 0) 1961 { 1962 uMask |= (pRegion->type & PCI_ADDRESS_SPACE_IO) ? 1963 (1 << 2) - 1 /* 2 lowest bits for IO region */ : 1964 (1 << 4) - 1 /* 4 lowest bits for memory region, also ROM enable bit for ROM region */; 1965 1966 } 1967 1968 uint8_t u8Old = PDMPciDevGetByte(pPciDev, uAddr) & uMask; 1969 u8Val = (u8Old & uMask) | (u8Val & ~uMask); 1970 1971 Log3(("ich9pciWriteBarByte: was %x writing %x\n", u8Old, u8Val)); 1972 1973 PCIDevSetByte(pPciDev, uAddr, u8Val); 1940 ich9pciWriteBarByte(pPciDev, iRegion - 1, off + 4, bVal); 1941 else 1942 { 1943 Assert(off <= 3 || (pRegion->type & PCI_ADDRESS_SPACE_BAR64)); 1944 if (pRegion->size != 0) 1945 { 1946 1947 uint32_t uAddr = ich9pciGetRegionReg(iRegion) + off; 1948 Assert((pRegion->size & (pRegion->size - 1)) == 0); /* Region size must be power of two. */ 1949 uint8_t bMask = ( (pRegion->size - 1) >> (off * 8) ) & 0xff; 1950 if (off == 0) 1951 bMask |= (pRegion->type & PCI_ADDRESS_SPACE_IO) 1952 ? (1 << 2) - 1 /* 2 lowest bits for IO region */ : 1953 (1 << 4) - 1 /* 4 lowest bits for memory region, also ROM enable bit for ROM region */; 1954 1955 uint8_t bOld = PDMPciDevGetByte(pPciDev, uAddr) & bMask; 1956 bVal = (bOld & bMask) | (bVal & ~bMask); 1957 1958 Log3(("ich9pciWriteBarByte: %x changed to %x\n", bOld, bVal)); 1959 1960 PCIDevSetByte(pPciDev, uAddr, bVal); 1961 } 1962 /* else: Region doesn't exist */ 1963 } 1974 1964 } 1975 1965 … … 1988 1978 Assert(cb <= 4); 1989 1979 1990 if ((uAddress + cb) > 256 && (uAddress + cb) < 4096) 1991 { 1980 if (uAddress + cb <= 256) 1981 { 1982 /* 1983 * MSI and MSI-X capabilites needs to be handled separately. 1984 */ 1985 if ( pciDevIsMsiCapable(pPciDev) 1986 && uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset < (uint32_t)pPciDev->Int.s.u8MsiCapSize) 1987 MsiPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), 1988 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), 1989 pPciDev, uAddress, u32Value, cb); 1990 else if ( pciDevIsMsixCapable(pPciDev) 1991 && uAddress - (uint32_t)pPciDev->Int.s.u8MsixCapOffset < (uint32_t)pPciDev->Int.s.u8MsixCapSize) 1992 MsixPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), 1993 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), 1994 pPciDev, uAddress, u32Value, cb); 1995 else 1996 { 1997 /* 1998 * Handle the writes byte-by-byte. 1999 */ 2000 bool fUpdateMappings = false; 2001 bool fP2PBridge = false; 2002 uint8_t bHeaderType = ich9pciGetByte(pPciDev, VBOX_PCI_HEADER_TYPE); 2003 while (cb-- > 0) 2004 { 2005 bool fWritable = false; 2006 switch (bHeaderType) 2007 { 2008 case 0x00: /* normal device */ 2009 case 0x80: /* multi-function device */ 2010 switch (uAddress) 2011 { 2012 /* Read-only registers */ 2013 case VBOX_PCI_VENDOR_ID: 2014 case VBOX_PCI_VENDOR_ID+1: 2015 case VBOX_PCI_DEVICE_ID: 2016 case VBOX_PCI_DEVICE_ID+1: 2017 case VBOX_PCI_REVISION_ID: 2018 case VBOX_PCI_CLASS_PROG: 2019 case VBOX_PCI_CLASS_SUB: 2020 case VBOX_PCI_CLASS_BASE: 2021 case VBOX_PCI_HEADER_TYPE: 2022 case VBOX_PCI_SUBSYSTEM_VENDOR_ID: 2023 case VBOX_PCI_SUBSYSTEM_VENDOR_ID+1: 2024 case VBOX_PCI_SUBSYSTEM_ID: 2025 case VBOX_PCI_SUBSYSTEM_ID+1: 2026 case VBOX_PCI_ROM_ADDRESS: 2027 case VBOX_PCI_ROM_ADDRESS+1: 2028 case VBOX_PCI_ROM_ADDRESS+2: 2029 case VBOX_PCI_ROM_ADDRESS+3: 2030 case VBOX_PCI_CAPABILITY_LIST: 2031 case VBOX_PCI_INTERRUPT_PIN: 2032 fWritable = false; 2033 break; 2034 /* Others can be written */ 2035 default: 2036 fWritable = true; 2037 break; 2038 } 2039 break; 2040 case 0x01: /* PCI-PCI bridge */ 2041 fP2PBridge = true; 2042 switch (uAddress) 2043 { 2044 /* Read-only registers */ 2045 case VBOX_PCI_VENDOR_ID: 2046 case VBOX_PCI_VENDOR_ID+1: 2047 case VBOX_PCI_DEVICE_ID: 2048 case VBOX_PCI_DEVICE_ID+1: 2049 case VBOX_PCI_REVISION_ID: 2050 case VBOX_PCI_CLASS_PROG: 2051 case VBOX_PCI_CLASS_SUB: 2052 case VBOX_PCI_CLASS_BASE: 2053 case VBOX_PCI_HEADER_TYPE: 2054 case VBOX_PCI_ROM_ADDRESS_BR: 2055 case VBOX_PCI_ROM_ADDRESS_BR+1: 2056 case VBOX_PCI_ROM_ADDRESS_BR+2: 2057 case VBOX_PCI_ROM_ADDRESS_BR+3: 2058 case VBOX_PCI_INTERRUPT_PIN: 2059 fWritable = false; 2060 break; 2061 default: 2062 fWritable = true; 2063 break; 2064 } 2065 break; 2066 default: 2067 AssertMsgFailed(("Unknown header type %x\n", PCIDevGetHeaderType(pPciDev))); 2068 fWritable = false; 2069 break; 2070 } 2071 2072 bool fRom = false; 2073 uint8_t bVal = (uint8_t)u32Value; 2074 switch (uAddress) 2075 { 2076 case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */ 2077 fUpdateMappings = true; 2078 goto l_default_case; 2079 case VBOX_PCI_COMMAND+1: /* Command register, bits 8-15. */ 2080 /* don't change reserved bits (11-15) */ 2081 bVal &= ~UINT32_C(0xf8); 2082 fUpdateMappings = true; 2083 goto l_default_case; 2084 case VBOX_PCI_STATUS: /* Status register, bits 0-7. */ 2085 /* don't change read-only bits => actually all lower bits are read-only */ 2086 bVal &= ~UINT32_C(0xff); 2087 /* status register, low part: clear bits by writing a '1' to the corresponding bit */ 2088 pPciDev->abConfig[uAddress] &= ~bVal; 2089 break; 2090 case VBOX_PCI_STATUS+1: /* Status register, bits 8-15. */ 2091 /* don't change read-only bits */ 2092 bVal &= ~UINT32_C(0x06); 2093 /* status register, high part: clear bits by writing a '1' to the corresponding bit */ 2094 pPciDev->abConfig[uAddress] &= ~bVal; 2095 break; 2096 case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS +1: case VBOX_PCI_ROM_ADDRESS +2: case VBOX_PCI_ROM_ADDRESS +3: 2097 fRom = true; 2098 case VBOX_PCI_BASE_ADDRESS_0: case VBOX_PCI_BASE_ADDRESS_0+1: case VBOX_PCI_BASE_ADDRESS_0+2: case VBOX_PCI_BASE_ADDRESS_0+3: 2099 case VBOX_PCI_BASE_ADDRESS_1: case VBOX_PCI_BASE_ADDRESS_1+1: case VBOX_PCI_BASE_ADDRESS_1+2: case VBOX_PCI_BASE_ADDRESS_1+3: 2100 case VBOX_PCI_BASE_ADDRESS_2: case VBOX_PCI_BASE_ADDRESS_2+1: case VBOX_PCI_BASE_ADDRESS_2+2: case VBOX_PCI_BASE_ADDRESS_2+3: 2101 case VBOX_PCI_BASE_ADDRESS_3: case VBOX_PCI_BASE_ADDRESS_3+1: case VBOX_PCI_BASE_ADDRESS_3+2: case VBOX_PCI_BASE_ADDRESS_3+3: 2102 case VBOX_PCI_BASE_ADDRESS_4: case VBOX_PCI_BASE_ADDRESS_4+1: case VBOX_PCI_BASE_ADDRESS_4+2: case VBOX_PCI_BASE_ADDRESS_4+3: 2103 case VBOX_PCI_BASE_ADDRESS_5: case VBOX_PCI_BASE_ADDRESS_5+1: case VBOX_PCI_BASE_ADDRESS_5+2: case VBOX_PCI_BASE_ADDRESS_5+3: 2104 /* We check that, as same PCI register numbers as BARs may mean different registers for bridges */ 2105 if (!fP2PBridge) 2106 { 2107 uint32_t iRegion = fRom ? VBOX_PCI_ROM_SLOT : (uAddress - VBOX_PCI_BASE_ADDRESS_0) >> 2; 2108 uint32_t off = uAddress & 0x3; 2109 ich9pciWriteBarByte(pPciDev, iRegion, off, bVal); 2110 fUpdateMappings = true; 2111 break; 2112 } 2113 /* fall thru (bridge) */ 2114 default: 2115 l_default_case: 2116 if (fWritable) 2117 PCIDevSetByte(pPciDev, uAddress, bVal); 2118 break; 2119 } 2120 uAddress++; 2121 u32Value >>= 8; 2122 } 2123 2124 /* 2125 * Update the region mappings if anything changed related to them (command, BARs, ROM). 2126 */ 2127 if (fUpdateMappings) 2128 ich9pciUpdateMappings(pPciDev); 2129 } 2130 } 2131 else if (uAddress + cb <= 4096) 1992 2132 LogRel(("PCI: %8s/%u: Write to extended register %d fallen back to generic code\n", 1993 2133 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, uAddress)); 1994 return; 1995 } 1996 1997 AssertMsgReturnVoid(uAddress + cb <= 256, ("Write after end of PCI config space\n")); 1998 1999 if ( pciDevIsMsiCapable(pPciDev) 2000 && (uAddress >= pPciDev->Int.s.u8MsiCapOffset) 2001 && (uAddress < (unsigned)(pPciDev->Int.s.u8MsiCapOffset + pPciDev->Int.s.u8MsiCapSize)) 2002 ) 2003 { 2004 MsiPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), 2005 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), 2006 pPciDev, uAddress, u32Value, cb); 2007 return; 2008 } 2009 2010 if ( pciDevIsMsixCapable(pPciDev) 2011 && (uAddress >= pPciDev->Int.s.u8MsixCapOffset) 2012 && (uAddress < (unsigned)(pPciDev->Int.s.u8MsixCapOffset + pPciDev->Int.s.u8MsixCapSize)) 2013 ) 2014 { 2015 MsixPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), 2016 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), 2017 pPciDev, uAddress, u32Value, cb); 2018 return; 2019 } 2020 2021 bool fUpdateMappings = false; 2022 bool fP2PBridge = false; 2023 uint8_t bHeaderType = ich9pciGetByte(pPciDev, VBOX_PCI_HEADER_TYPE); 2024 while (cb-- > 0) 2025 { 2026 bool fWritable = false; 2027 switch (bHeaderType) 2028 { 2029 case 0x00: /* normal device */ 2030 case 0x80: /* multi-function device */ 2031 switch (uAddress) 2032 { 2033 /* Read-only registers */ 2034 case VBOX_PCI_VENDOR_ID: 2035 case VBOX_PCI_VENDOR_ID+1: 2036 case VBOX_PCI_DEVICE_ID: 2037 case VBOX_PCI_DEVICE_ID+1: 2038 case VBOX_PCI_REVISION_ID: 2039 case VBOX_PCI_CLASS_PROG: 2040 case VBOX_PCI_CLASS_SUB: 2041 case VBOX_PCI_CLASS_BASE: 2042 case VBOX_PCI_HEADER_TYPE: 2043 case VBOX_PCI_SUBSYSTEM_VENDOR_ID: 2044 case VBOX_PCI_SUBSYSTEM_VENDOR_ID+1: 2045 case VBOX_PCI_SUBSYSTEM_ID: 2046 case VBOX_PCI_SUBSYSTEM_ID+1: 2047 case VBOX_PCI_ROM_ADDRESS: 2048 case VBOX_PCI_ROM_ADDRESS+1: 2049 case VBOX_PCI_ROM_ADDRESS+2: 2050 case VBOX_PCI_ROM_ADDRESS+3: 2051 case VBOX_PCI_CAPABILITY_LIST: 2052 case VBOX_PCI_INTERRUPT_PIN: 2053 fWritable = false; 2054 break; 2055 /* Others can be written */ 2056 default: 2057 fWritable = true; 2058 break; 2059 } 2060 break; 2061 case 0x01: /* PCI-PCI bridge */ 2062 fP2PBridge = true; 2063 switch (uAddress) 2064 { 2065 /* Read-only registers */ 2066 case VBOX_PCI_VENDOR_ID: 2067 case VBOX_PCI_VENDOR_ID+1: 2068 case VBOX_PCI_DEVICE_ID: 2069 case VBOX_PCI_DEVICE_ID+1: 2070 case VBOX_PCI_REVISION_ID: 2071 case VBOX_PCI_CLASS_PROG: 2072 case VBOX_PCI_CLASS_SUB: 2073 case VBOX_PCI_CLASS_BASE: 2074 case VBOX_PCI_HEADER_TYPE: 2075 case VBOX_PCI_ROM_ADDRESS_BR: 2076 case VBOX_PCI_ROM_ADDRESS_BR+1: 2077 case VBOX_PCI_ROM_ADDRESS_BR+2: 2078 case VBOX_PCI_ROM_ADDRESS_BR+3: 2079 case VBOX_PCI_INTERRUPT_PIN: 2080 fWritable = false; 2081 break; 2082 default: 2083 fWritable = true; 2084 break; 2085 } 2086 break; 2087 default: 2088 AssertMsgFailed(("Unknown header type %x\n", PCIDevGetHeaderType(pPciDev))); 2089 fWritable = false; 2090 break; 2091 } 2092 2093 bool fRom = false; 2094 uint8_t bVal = (uint8_t)u32Value; 2095 switch (uAddress) 2096 { 2097 case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */ 2098 fUpdateMappings = true; 2099 goto l_default_case; 2100 case VBOX_PCI_COMMAND+1: /* Command register, bits 8-15. */ 2101 /* don't change reserved bits (11-15) */ 2102 bVal &= ~UINT32_C(0xf8); 2103 fUpdateMappings = true; 2104 goto l_default_case; 2105 case VBOX_PCI_STATUS: /* Status register, bits 0-7. */ 2106 /* don't change read-only bits => actually all lower bits are read-only */ 2107 bVal &= ~UINT32_C(0xff); 2108 /* status register, low part: clear bits by writing a '1' to the corresponding bit */ 2109 pPciDev->abConfig[uAddress] &= ~bVal; 2110 break; 2111 case VBOX_PCI_STATUS+1: /* Status register, bits 8-15. */ 2112 /* don't change read-only bits */ 2113 bVal &= ~UINT32_C(0x06); 2114 /* status register, high part: clear bits by writing a '1' to the corresponding bit */ 2115 pPciDev->abConfig[uAddress] &= ~bVal; 2116 break; 2117 case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS +1: case VBOX_PCI_ROM_ADDRESS +2: case VBOX_PCI_ROM_ADDRESS +3: 2118 fRom = true; 2119 case VBOX_PCI_BASE_ADDRESS_0: case VBOX_PCI_BASE_ADDRESS_0+1: case VBOX_PCI_BASE_ADDRESS_0+2: case VBOX_PCI_BASE_ADDRESS_0+3: 2120 case VBOX_PCI_BASE_ADDRESS_1: case VBOX_PCI_BASE_ADDRESS_1+1: case VBOX_PCI_BASE_ADDRESS_1+2: case VBOX_PCI_BASE_ADDRESS_1+3: 2121 case VBOX_PCI_BASE_ADDRESS_2: case VBOX_PCI_BASE_ADDRESS_2+1: case VBOX_PCI_BASE_ADDRESS_2+2: case VBOX_PCI_BASE_ADDRESS_2+3: 2122 case VBOX_PCI_BASE_ADDRESS_3: case VBOX_PCI_BASE_ADDRESS_3+1: case VBOX_PCI_BASE_ADDRESS_3+2: case VBOX_PCI_BASE_ADDRESS_3+3: 2123 case VBOX_PCI_BASE_ADDRESS_4: case VBOX_PCI_BASE_ADDRESS_4+1: case VBOX_PCI_BASE_ADDRESS_4+2: case VBOX_PCI_BASE_ADDRESS_4+3: 2124 case VBOX_PCI_BASE_ADDRESS_5: case VBOX_PCI_BASE_ADDRESS_5+1: case VBOX_PCI_BASE_ADDRESS_5+2: case VBOX_PCI_BASE_ADDRESS_5+3: 2125 /* We check that, as same PCI register numbers as BARs may mean different registers for bridges */ 2126 if (!fP2PBridge) 2127 { 2128 2129 uint32_t iRegion = fRom ? VBOX_PCI_ROM_SLOT : (uAddress - VBOX_PCI_BASE_ADDRESS_0) >> 2; 2130 uint32_t off = uAddress & 0x3; 2131 ich9pciWriteBarByte(pPciDev, iRegion, off, bVal); 2132 fUpdateMappings = true; 2133 break; 2134 } 2135 /* fall thru (bridge) */ 2136 default: 2137 l_default_case: 2138 if (fWritable) 2139 PCIDevSetByte(pPciDev, uAddress, bVal); 2140 break; 2141 } 2142 uAddress++; 2143 u32Value >>= 8; 2144 } 2145 2146 if (fUpdateMappings) 2147 /* if the command/base address register is modified, we must modify the mappings */ 2148 ich9pciUpdateMappings(pPciDev); 2134 else 2135 AssertMsgFailed(("Write after end of PCI config space\n")); 2149 2136 } 2150 2137
Note:
See TracChangeset
for help on using the changeset viewer.