VirtualBox

Changeset 64457 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 28, 2016 1:51:57 PM (8 years ago)
Author:
vboxsync
Message:

DevPci: Cleaning up ich9pciConfigWriteDev.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevPciIch9.cpp

    r64456 r64457  
    732732DECLINLINE(uint32_t) ich9pciGetRegionReg(int iRegion)
    733733{
    734     return (iRegion == VBOX_PCI_ROM_SLOT) ?
    735             VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
     734    return iRegion == VBOX_PCI_ROM_SLOT
     735         ?  VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
    736736}
    737737
     
    19311931
    19321932
    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);
     1933DECLINLINE(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));
    19431937
    19441938    /* Check if we're writing to upper part of 64-bit BAR. */
    19451939    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    }
    19741964}
    19751965
     
    19881978    Assert(cb <= 4);
    19891979
    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)
    19922132        LogRel(("PCI: %8s/%u: Write to extended register %d fallen back to generic code\n",
    19932133                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"));
    21492136}
    21502137
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette