Changeset 62553 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- Jul 26, 2016 8:39:53 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 109122
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevACPI.cpp
r62509 r62553 64 64 #define DEBUG_CHR 0x3001 65 65 66 /** PM Base Address PCI config space offset */ 67 #define PMBA 0x40 68 /** PM Miscellaneous Power Management PCI config space offset */ 69 #define PMREGMISC 0x80 70 66 71 #define PM_TMR_FREQ 3579545 67 /* Default base for PM PIIX4 device */72 /** Default base for PM PIIX4 device */ 68 73 #define PM_PORT_BASE 0x4000 69 74 /* Port offsets in PM device */ … … 204 209 #define STA_BATTERY_PRESENT_MASK RT_BIT(4) /**< the battery is present */ 205 210 211 /** SMBus Base Address PCI config space offset */ 212 #define SMBBA 0x90 213 /** SMBus Host Configuration PCI config space offset */ 214 #define SMBHSTCFG 0xd2 215 /** SMBus Slave Command PCI config space offset */ 216 #define SMBSLVC 0xd3 217 /** SMBus Slave Shadow Port 1 PCI config space offset */ 218 #define SMBSHDW1 0xd4 219 /** SMBus Slave Shadow Port 2 PCI config space offset */ 220 #define SMBSHDW2 0xd5 221 /** SMBus Revision Identification PCI config space offset */ 222 #define SMBREV 0xd6 223 224 #define SMBHSTCFG_SMB_HST_EN RT_BIT(0) 225 #define SMBHSTCFG_INTRSEL (RT_BIT(1) | RT_BIT(2) | RT_BIT(3)) 226 #define SMBHSTCFG_INTRSEL_SMI 0 227 #define SMBHSTCFG_INTRSEL_IRQ9 4 228 #define SMBHSTCFG_INTRSEL_SHIFT 1 229 230 /** Default base for SMBus PIIX4 device */ 231 #define SMB_PORT_BASE 0x4100 232 233 /** SMBus Host Status Register I/O offset */ 234 #define SMBHSTSTS_OFF 0x0000 235 /** SMBus Slave Status Register I/O offset */ 236 #define SMBSLVSTS_OFF 0x0001 237 /** SMBus Host Count Register I/O offset */ 238 #define SMBHSTCNT_OFF 0x0002 239 /** SMBus Host Command Register I/O offset */ 240 #define SMBHSTCMD_OFF 0x0003 241 /** SMBus Host Address Register I/O offset */ 242 #define SMBHSTADD_OFF 0x0004 243 /** SMBus Host Data 0 Register I/O offset */ 244 #define SMBHSTDAT0_OFF 0x0005 245 /** SMBus Host Data 1 Register I/O offset */ 246 #define SMBHSTDAT1_OFF 0x0006 247 /** SMBus Block Data Register I/O offset */ 248 #define SMBBLKDAT_OFF 0x0007 249 /** SMBus Slave Control Register I/O offset */ 250 #define SMBSLVCNT_OFF 0x0008 251 /** SMBus Shadow Command Register I/O offset */ 252 #define SMBSHDWCMD_OFF 0x0009 253 /** SMBus Slave Event Register I/O offset */ 254 #define SMBSLVEVT_OFF 0x000a 255 /** SMBus Slave Data Register I/O offset */ 256 #define SMBSLVDAT_OFF 0x000c 257 258 #define SMBHSTSTS_HOST_BUSY RT_BIT(0) 259 #define SMBHSTSTS_INTER RT_BIT(1) 260 #define SMBHSTSTS_DEV_ERR RT_BIT(2) 261 #define SMBHSTSTS_BUS_ERR RT_BIT(3) 262 #define SMBHSTSTS_FAILED RT_BIT(4) 263 #define SMBHSTSTS_INT_MASK (SMBHSTSTS_INTER | SMBHSTSTS_DEV_ERR | SMBHSTSTS_BUS_ERR | SMBHSTSTS_FAILED) 264 265 #define SMBSLVSTS_WRITE_MASK 0x3c 266 267 #define SMBHSTCNT_INTEREN RT_BIT(0) 268 #define SMBHSTCNT_KILL RT_BIT(1) 269 #define SMBHSTCNT_CMD_PROT (RT_BIT(2) | RT_BIT(3) | RT_BIT(4)) 270 #define SMBHSTCNT_START RT_BIT(6) 271 #define SMBHSTCNT_WRITE_MASK (SMBHSTCNT_INTEREN | SMBHSTCNT_KILL | SMBHSTCNT_CMD_PROT) 272 273 #define SMBSLVCNT_WRITE_MASK (RT_BIT(0) | RT_BIT(1) | RT_BIT(2) | RT_BIT(3)) 274 206 275 207 276 /********************************************************************************************************************************* … … 271 340 /** I/O port address of PM device. */ 272 341 RTIOPORT uPmIoPortBase; 342 /** I/O port address of SMBus device. */ 343 RTIOPORT uSMBusIoPortBase; 273 344 /** Flag whether the GC part of the device is enabled. */ 274 345 bool fGCEnabled; … … 305 376 /** PCI address of the host bus controller device. */ 306 377 uint32_t u32HbcPciAddress; 378 379 uint32_t Alignment1; 380 307 381 /* Physical address of PCI config space MMIO region */ 308 382 uint64_t u64PciConfigMMioAddress; … … 338 412 /** @} */ 339 413 340 uint32_t u32Alignment1;414 uint32_t Alignment2; 341 415 342 416 /** ACPI port base interface. */ … … 349 423 PPDMDEVINSRC pDevInsRC; 350 424 351 uint32_t Alignment 2;425 uint32_t Alignment3; 352 426 /** Pointer to the driver base interface. */ 353 427 R3PTRTYPE(PPDMIBASE) pDrvBase; … … 372 446 /** ACPI custom OEM Rev */ 373 447 uint32_t u32OemRevision; 374 uint32_t Alignment 3;448 uint32_t Alignment4; 375 449 376 450 /** The custom table binary data. */ … … 378 452 /** The size of the custom table binary. */ 379 453 uint64_t cbCustBin; 454 455 /** SMBus Host Status Register */ 456 uint8_t u8SMBusHstSts; 457 /** SMBus Slave Status Register */ 458 uint8_t u8SMBusSlvSts; 459 /** SMBus Host Control Register */ 460 uint8_t u8SMBusHstCnt; 461 /** SMBus Host Command Register */ 462 uint8_t u8SMBusHstCmd; 463 /** SMBus Host Address Register */ 464 uint8_t u8SMBusHstAdd; 465 /** SMBus Host Data 0 Register */ 466 uint8_t u8SMBusHstDat0; 467 /** SMBus Host Data 1 Register */ 468 uint8_t u8SMBusHstDat1; 469 /** SMBus Slave Control Register */ 470 uint8_t u8SMBusSlvCnt; 471 /** SMBus Shadow Command Register */ 472 uint8_t u8SMBusShdwCmd; 473 /** SMBus Slave Event Register */ 474 uint16_t u16SMBusSlvEvt; 475 /** SMBus Slave Data Register */ 476 uint16_t u16SMBusSlvDat; 477 /** SMBus Host Block Data Buffer */ 478 uint8_t au8SMBusBlkDat[32]; 479 /** SMBus Host Block Index */ 480 uint8_t u8SMBusBlkIdx; 380 481 } ACPIState; 381 482 … … 672 773 #endif 673 774 674 /* SCI IRQ*/775 /* SCI, usually IRQ9 */ 675 776 DECLINLINE(void) acpiSetIrq(ACPIState *pThis, int level) 676 777 { 677 if (pThis->pm1a_ctl & SCI_EN) 678 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, level); 679 } 680 681 DECLINLINE(uint32_t) pm1a_pure_en(uint32_t en) 682 { 683 return en & ~(RSR_EN | IGN_EN); 684 } 685 686 DECLINLINE(uint32_t) pm1a_pure_sts(uint32_t sts) 687 { 688 return sts & ~(RSR_STS | IGN_STS); 689 } 690 691 DECLINLINE(int) pm1a_level(ACPIState *pThis) 692 { 693 return (pm1a_pure_en(pThis->pm1a_en) & pm1a_pure_sts(pThis->pm1a_sts)) != 0; 778 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, level); 779 } 780 781 DECLINLINE(bool) pm1a_level(ACPIState *pThis) 782 { 783 return (pThis->pm1a_ctl & SCI_EN) 784 && (pThis->pm1a_en & pThis->pm1a_sts & ~(RSR_EN | IGN_EN)); 694 785 } 695 786 696 787 DECLINLINE(bool) gpe0_level(ACPIState *pThis) 697 788 { 698 return (pThis->gpe0_en & pThis->gpe0_sts) != 0; 789 return (pThis->gpe0_en & pThis->gpe0_sts); 790 } 791 792 DECLINLINE(bool) smbus_level(ACPIState *pThis) 793 { 794 return (pThis->u8SMBusHstCnt & SMBHSTCNT_INTEREN) 795 && (pThis->dev.config[SMBHSTCFG] & SMBHSTCFG_SMB_HST_EN) 796 && (pThis->dev.config[SMBHSTCFG] & SMBHSTCFG_INTRSEL) == SMBHSTCFG_INTRSEL_IRQ9 << SMBHSTCFG_INTRSEL_SHIFT 797 && (pThis->u8SMBusHstSts & SMBHSTSTS_INT_MASK); 798 } 799 800 DECLINLINE(bool) acpiSCILevel(ACPIState *pThis) 801 { 802 return pm1a_level(pThis) || gpe0_level(pThis) || smbus_level(pThis); 699 803 } 700 804 … … 715 819 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 716 820 717 if (gpe0_level(pThis)) 718 return; 719 720 int const old_level = pm1a_level(pThis); 721 int const new_level = (pm1a_pure_en(en) & pm1a_pure_sts(sts)) != 0; 722 723 Log(("apicUpdatePm1a() old=%x new=%x\n", old_level, new_level)); 724 821 const bool old_level = acpiSCILevel(pThis); 725 822 pThis->pm1a_en = en; 726 823 pThis->pm1a_sts = sts; 824 const bool new_level = acpiSCILevel(pThis); 825 826 LogFunc(("old=%x new=%x\n", old_level, new_level)); 727 827 728 828 if (new_level != old_level) … … 746 846 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 747 847 748 if (pm1a_level(pThis)) 749 return; 750 751 int const old_level = gpe0_level(pThis); 752 int const new_level = (en & sts) != 0; 753 848 const bool old_level = acpiSCILevel(pThis); 754 849 pThis->gpe0_en = en; 755 850 pThis->gpe0_sts = sts; 851 const bool new_level = acpiSCILevel(pThis); 852 853 LogFunc(("old=%x new=%x\n", old_level, new_level)); 756 854 757 855 if (new_level != old_level) … … 1294 1392 case SYSTEM_INFO_INDEX_PCI_LENGTH: 1295 1393 /** @todo couldn't MCFG be in 64-bit range? */ 1296 Assert(pThis->u64PciConfigMMioLength < 0xffffffff);1394 Assert(pThis->u64PciConfigMMioLength < 0xffffffff); 1297 1395 *pu32 = (uint32_t)pThis->u64PciConfigMMioLength; 1298 1396 break; … … 1823 1921 1824 1922 /** 1923 * Called by acpiR3Reset and acpiR3Construct to set up the PM PCI config space. 1924 * 1925 * @param pThis The ACPI instance. 1926 */ 1927 static void acpiR3PmPCIBIOSFake(ACPIState *pThis) 1928 { 1929 pThis->dev.config[PMBA ] = pThis->uPmIoPortBase | 1; /* PMBA, PM base address, bit 0 marks it as IO range */ 1930 pThis->dev.config[PMBA+1] = pThis->uPmIoPortBase >> 8; 1931 pThis->dev.config[PMBA+2] = 0x00; 1932 pThis->dev.config[PMBA+3] = 0x00; 1933 } 1934 1935 /** 1825 1936 * Used to calculate the value of a PM I/O port. 1826 1937 * … … 1848 1959 static int acpiR3RegisterPmHandlers(ACPIState *pThis) 1849 1960 { 1850 int rc = VINF_SUCCESS; 1961 if (pThis->uPmIoPortBase == 0) 1962 return VINF_SUCCESS; 1851 1963 1852 1964 #define R(offset, cnt, writer, reader, description) \ 1853 1965 do { \ 1854 rc = PDMDevHlpIOPortRegister(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, offset), cnt, pThis, writer, reader, \1855 NULL, NULL, description); \1966 int rc = PDMDevHlpIOPortRegister(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, offset), cnt, pThis, writer, reader, \ 1967 NULL, NULL, description); \ 1856 1968 if (RT_FAILURE(rc)) \ 1857 1969 return rc; \ … … 1871 1983 if (pThis->fGCEnabled) 1872 1984 { 1873 rc = PDMDevHlpIOPortRegisterRC(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET),1874 1, 0, NULL, "acpiPMTmrRead",1875 NULL, NULL, "ACPI PM Timer");1985 int rc = PDMDevHlpIOPortRegisterRC(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET), 1986 1, 0, NULL, "acpiPMTmrRead", 1987 NULL, NULL, "ACPI PM Timer"); 1876 1988 AssertRCReturn(rc, rc); 1877 1989 } … … 1880 1992 if (pThis->fR0Enabled) 1881 1993 { 1882 rc = PDMDevHlpIOPortRegisterR0(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET),1883 1, 0, NULL, "acpiPMTmrRead",1884 NULL, NULL, "ACPI PM Timer");1994 int rc = PDMDevHlpIOPortRegisterR0(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET), 1995 1, 0, NULL, "acpiPMTmrRead", 1996 NULL, NULL, "ACPI PM Timer"); 1885 1997 AssertRCReturn(rc, rc); 1886 1998 } 1887 1999 1888 return rc;2000 return VINF_SUCCESS; 1889 2001 } 1890 2002 … … 1898 2010 static int acpiR3UnregisterPmHandlers(ACPIState *pThis) 1899 2011 { 2012 if (pThis->uPmIoPortBase == 0) 2013 return VINF_SUCCESS; 2014 1900 2015 #define U(offset, cnt) \ 1901 2016 do { \ … … 1946 2061 if (RT_FAILURE(rc)) 1947 2062 return rc; 2063 } 2064 2065 return VINF_SUCCESS; 2066 } 2067 2068 /** 2069 * @callback_method_impl{FNIOMIOPORTOUT, SMBus} 2070 */ 2071 PDMBOTHCBDECL(int) acpiR3SMBusWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 2072 { 2073 ACPIState *pThis = (ACPIState *)pvUser; 2074 DEVACPI_LOCK_R3(pThis); 2075 2076 LogFunc(("Port=%#x u32=%#x cb=%u\n", Port, u32, cb)); 2077 uint8_t off = Port & 0x000f; 2078 if ( (cb != 1 && off <= SMBSHDWCMD_OFF) 2079 || (cb != 2 && (off == SMBSLVEVT_OFF || off == SMBSLVDAT_OFF))) 2080 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 2081 2082 switch (off) 2083 { 2084 case SMBHSTSTS_OFF: 2085 /* Bit 0 is readonly, bits 1..4 are write clear, bits 5..7 are reserved */ 2086 pThis->u8SMBusHstSts &= ~(u32 & SMBHSTSTS_INT_MASK); 2087 break; 2088 case SMBSLVSTS_OFF: 2089 /* Bit 0 is readonly, bit 1 is reserved, bits 2..5 are write clear, bits 6..7 are reserved */ 2090 pThis->u8SMBusSlvSts &= ~(u32 & SMBSLVSTS_WRITE_MASK); 2091 break; 2092 case SMBHSTCNT_OFF: 2093 { 2094 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 2095 2096 const bool old_level = acpiSCILevel(pThis); 2097 pThis->u8SMBusHstCnt = u32 & SMBHSTCNT_WRITE_MASK; 2098 if (u32 & SMBHSTCNT_START) 2099 { 2100 /* Start, trigger error as this is a dummy implementation */ 2101 pThis->u8SMBusHstSts |= SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTER; 2102 } 2103 if (u32 & SMBHSTCNT_KILL) 2104 { 2105 /* Kill */ 2106 pThis->u8SMBusHstSts |= SMBHSTSTS_FAILED | SMBHSTSTS_INTER; 2107 } 2108 const bool new_level = acpiSCILevel(pThis); 2109 2110 LogFunc(("old=%x new=%x\n", old_level, new_level)); 2111 2112 /* This handles only SCI/IRQ9. SMI# makes not much sense today and 2113 * needs to be implemented later if it ever becomes relevant. */ 2114 if (new_level != old_level) 2115 acpiSetIrq(pThis, new_level); 2116 break; 2117 } 2118 case SMBHSTCMD_OFF: 2119 pThis->u8SMBusHstCmd = u32; 2120 break; 2121 case SMBHSTADD_OFF: 2122 pThis->u8SMBusHstAdd = u32; 2123 break; 2124 case SMBHSTDAT0_OFF: 2125 pThis->u8SMBusHstDat0 = u32; 2126 break; 2127 case SMBHSTDAT1_OFF: 2128 pThis->u8SMBusHstDat1 = u32; 2129 break; 2130 case SMBBLKDAT_OFF: 2131 pThis->au8SMBusBlkDat[pThis->u8SMBusBlkIdx] = u32; 2132 pThis->u8SMBusBlkIdx++; 2133 pThis->u8SMBusBlkIdx &= sizeof(pThis->au8SMBusBlkDat) - 1; 2134 break; 2135 case SMBSLVCNT_OFF: 2136 pThis->u8SMBusSlvCnt = u32 & SMBSLVCNT_WRITE_MASK; 2137 break; 2138 case SMBSHDWCMD_OFF: 2139 /* readonly register */ 2140 break; 2141 case SMBSLVEVT_OFF: 2142 pThis->u16SMBusSlvEvt = u32; 2143 break; 2144 case SMBSLVDAT_OFF: 2145 /* readonly register */ 2146 break; 2147 default: 2148 /* caught by the sanity check above */ 2149 ; 2150 } 2151 2152 DEVACPI_UNLOCK(pThis); 2153 return VINF_SUCCESS; 2154 } 2155 2156 /** 2157 * @callback_method_impl{FNIOMIOPORTIN, SMBus} 2158 */ 2159 PDMBOTHCBDECL(int) acpiR3SMBusRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 2160 { 2161 ACPIState *pThis = (ACPIState *)pvUser; 2162 DEVACPI_LOCK_R3(pThis); 2163 2164 int rc = VINF_SUCCESS; 2165 LogFunc(("Port=%#x cb=%u\n", Port, cb)); 2166 uint8_t off = Port & 0x000f; 2167 if ( (cb != 1 && off <= SMBSHDWCMD_OFF) 2168 || (cb != 2 && (off == SMBSLVEVT_OFF || off == SMBSLVDAT_OFF))) 2169 return VERR_IOM_IOPORT_UNUSED; 2170 2171 switch (off) 2172 { 2173 case SMBHSTSTS_OFF: 2174 *pu32 = pThis->u8SMBusHstSts; 2175 break; 2176 case SMBSLVSTS_OFF: 2177 *pu32 = pThis->u8SMBusSlvSts; 2178 break; 2179 case SMBHSTCNT_OFF: 2180 pThis->u8SMBusBlkIdx = 0; 2181 *pu32 = pThis->u8SMBusHstCnt; 2182 break; 2183 case SMBHSTCMD_OFF: 2184 *pu32 = pThis->u8SMBusHstCmd; 2185 break; 2186 case SMBHSTADD_OFF: 2187 *pu32 = pThis->u8SMBusHstAdd; 2188 break; 2189 case SMBHSTDAT0_OFF: 2190 *pu32 = pThis->u8SMBusHstDat0; 2191 break; 2192 case SMBHSTDAT1_OFF: 2193 *pu32 = pThis->u8SMBusHstDat1; 2194 break; 2195 case SMBBLKDAT_OFF: 2196 *pu32 = pThis->au8SMBusBlkDat[pThis->u8SMBusBlkIdx]; 2197 pThis->u8SMBusBlkIdx++; 2198 pThis->u8SMBusBlkIdx &= sizeof(pThis->au8SMBusBlkDat) - 1; 2199 break; 2200 case SMBSLVCNT_OFF: 2201 *pu32 = pThis->u8SMBusSlvCnt; 2202 break; 2203 case SMBSHDWCMD_OFF: 2204 *pu32 = pThis->u8SMBusShdwCmd; 2205 break; 2206 case SMBSLVEVT_OFF: 2207 *pu32 = pThis->u16SMBusSlvEvt; 2208 break; 2209 case SMBSLVDAT_OFF: 2210 *pu32 = pThis->u16SMBusSlvDat; 2211 break; 2212 default: 2213 /* caught by the sanity check above */ 2214 rc = VERR_IOM_IOPORT_UNUSED; 2215 } 2216 2217 DEVACPI_UNLOCK(pThis); 2218 LogFunc(("Port=%#x u32=%#x cb=%u rc=%Rrc\n", Port, *pu32, cb, rc)); 2219 return rc; 2220 } 2221 2222 /** 2223 * Called by acpiR3Reset and acpiR3Construct to set up the SMBus PCI config space. 2224 * 2225 * @param pThis The ACPI instance. 2226 */ 2227 static void acpiR3SMBusPCIBIOSFake(ACPIState *pThis) 2228 { 2229 pThis->dev.config[SMBBA ] = pThis->uSMBusIoPortBase | 1; /* SMBBA, SMBus base address, bit 0 marks it as IO range */ 2230 pThis->dev.config[SMBBA+1] = pThis->uSMBusIoPortBase >> 8; 2231 pThis->dev.config[SMBBA+2] = 0x00; 2232 pThis->dev.config[SMBBA+3] = 0x00; 2233 pThis->dev.config[SMBHSTCFG] = SMBHSTCFG_INTRSEL_IRQ9 << SMBHSTCFG_INTRSEL_SHIFT | SMBHSTCFG_SMB_HST_EN; /* SMBHSTCFG */ 2234 pThis->dev.config[SMBSLVC] = 0x00; /* SMBSLVC */ 2235 pThis->dev.config[SMBSHDW1] = 0x00; /* SMBSHDW1 */ 2236 pThis->dev.config[SMBSHDW2] = 0x00; /* SMBSHDW2 */ 2237 pThis->dev.config[SMBREV] = 0x00; /* SMBREV */ 2238 } 2239 2240 /** 2241 * Called by acpiR3LoadState, acpiR3Reset and acpiR3Construct to reset the SMBus device register state. 2242 * 2243 * @param pThis The ACPI instance. 2244 */ 2245 static void acpiR3SMBusResetDevice(ACPIState *pThis) 2246 { 2247 pThis->u8SMBusHstSts = 0x00; 2248 pThis->u8SMBusSlvSts = 0x00; 2249 pThis->u8SMBusHstCnt = 0x00; 2250 pThis->u8SMBusHstCmd = 0x00; 2251 pThis->u8SMBusHstAdd = 0x00; 2252 pThis->u8SMBusHstDat0 = 0x00; 2253 pThis->u8SMBusHstDat1 = 0x00; 2254 pThis->u8SMBusSlvCnt = 0x00; 2255 pThis->u8SMBusShdwCmd = 0x00; 2256 pThis->u16SMBusSlvEvt = 0x0000; 2257 pThis->u16SMBusSlvDat = 0x0000; 2258 memset(pThis->au8SMBusBlkDat, 0x00, sizeof(pThis->au8SMBusBlkDat)); 2259 pThis->u8SMBusBlkIdx = 0; 2260 } 2261 2262 /** 2263 * Called by acpiR3LoadState and acpiR3UpdateSMBusHandlers to register the SMBus ports. 2264 * 2265 * @returns VBox status code. 2266 * @param pThis The ACPI instance. 2267 */ 2268 static int acpiR3RegisterSMBusHandlers(ACPIState *pThis) 2269 { 2270 int rc = VINF_SUCCESS; 2271 2272 if (pThis->uSMBusIoPortBase == 0) 2273 return VINF_SUCCESS; 2274 2275 rc = PDMDevHlpIOPortRegister(pThis->pDevInsR3, pThis->uSMBusIoPortBase, 16, pThis, acpiR3SMBusWrite, acpiR3SMBusRead, NULL, NULL, "SMBus"); 2276 if (RT_FAILURE(rc)) 2277 return rc; 2278 2279 return VINF_SUCCESS; 2280 } 2281 2282 /** 2283 * Called by acpiR3LoadState and acpiR3UpdateSMBusHandlers to unregister the SMBus ports. 2284 * 2285 * @returns VBox status code. 2286 * @param pThis The ACPI instance. 2287 */ 2288 static int acpiR3UnregisterSMBusHandlers(ACPIState *pThis) 2289 { 2290 if (pThis->uSMBusIoPortBase == 0) 2291 return VINF_SUCCESS; 2292 2293 int rc = PDMDevHlpIOPortDeregister(pThis->pDevInsR3, pThis->uSMBusIoPortBase, 16); 2294 AssertRCReturn(rc, rc); 2295 2296 return VINF_SUCCESS; 2297 } 2298 2299 /** 2300 * Called by acpiR3PciConfigWrite and acpiReset to change the location of the 2301 * SMBus ports. 2302 * 2303 * @returns VBox status code. 2304 * 2305 * @param pThis The ACPI instance. 2306 * @param NewIoPortBase The new base address of the I/O ports. 2307 */ 2308 static int acpiR3UpdateSMBusHandlers(ACPIState *pThis, RTIOPORT NewIoPortBase) 2309 { 2310 Log(("acpi: rebasing SMBus 0x%x -> 0x%x\n", pThis->uSMBusIoPortBase, NewIoPortBase)); 2311 if (NewIoPortBase != pThis->uSMBusIoPortBase) 2312 { 2313 int rc = acpiR3UnregisterSMBusHandlers(pThis); 2314 if (RT_FAILURE(rc)) 2315 return rc; 2316 2317 pThis->uSMBusIoPortBase = NewIoPortBase; 2318 2319 rc = acpiR3RegisterSMBusHandlers(pThis); 2320 if (RT_FAILURE(rc)) 2321 return rc; 2322 2323 #if 0 /* is there an FADT table entry for the SMBus base? */ 2324 /* We have to update FADT table acccording to the new base */ 2325 rc = acpiR3PlantTables(pThis); 2326 AssertRC(rc); 2327 if (RT_FAILURE(rc)) 2328 return rc; 2329 #endif 1948 2330 } 1949 2331 … … 2033 2415 2034 2416 /** 2417 * Saved state structure description, version 8. 2418 */ 2419 static const SSMFIELD g_AcpiSavedStateFields8[] = 2420 { 2421 SSMFIELD_ENTRY(ACPIState, pm1a_en), 2422 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 2423 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 2424 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 2425 SSMFIELD_ENTRY(ACPIState, uPmTimerVal), 2426 SSMFIELD_ENTRY(ACPIState, gpe0_en), 2427 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 2428 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 2429 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 2430 SSMFIELD_ENTRY(ACPIState, uSleepState), 2431 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 2432 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase), 2433 SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState), 2434 SSMFIELD_ENTRY(ACPIState, uSMBusIoPortBase), 2435 SSMFIELD_ENTRY(ACPIState, u8SMBusHstSts), 2436 SSMFIELD_ENTRY(ACPIState, u8SMBusSlvSts), 2437 SSMFIELD_ENTRY(ACPIState, u8SMBusHstCnt), 2438 SSMFIELD_ENTRY(ACPIState, u8SMBusHstCmd), 2439 SSMFIELD_ENTRY(ACPIState, u8SMBusHstAdd), 2440 SSMFIELD_ENTRY(ACPIState, u8SMBusHstDat0), 2441 SSMFIELD_ENTRY(ACPIState, u8SMBusHstDat1), 2442 SSMFIELD_ENTRY(ACPIState, u8SMBusSlvCnt), 2443 SSMFIELD_ENTRY(ACPIState, u8SMBusShdwCmd), 2444 SSMFIELD_ENTRY(ACPIState, u16SMBusSlvEvt), 2445 SSMFIELD_ENTRY(ACPIState, u16SMBusSlvDat), 2446 SSMFIELD_ENTRY(ACPIState, au8SMBusBlkDat), 2447 SSMFIELD_ENTRY(ACPIState, u8SMBusBlkIdx), 2448 SSMFIELD_ENTRY_TERM() 2449 }; 2450 2451 /** 2035 2452 * @callback_method_impl{FNSSMDEVSAVEEXEC} 2036 2453 */ … … 2038 2455 { 2039 2456 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 2040 return SSMR3PutStruct(pSSM, pThis, &g_AcpiSavedStateFields 7[0]);2457 return SSMR3PutStruct(pSSM, pThis, &g_AcpiSavedStateFields8[0]); 2041 2458 } 2042 2459 … … 2057 2474 return rc; 2058 2475 2476 /* 2477 * Unregister SMBus handlers, will register with actual base after state 2478 * successfully loaded. 2479 */ 2480 rc = acpiR3UnregisterSMBusHandlers(pThis); 2481 if (RT_FAILURE(rc)) 2482 return rc; 2483 acpiR3SMBusResetDevice(pThis); 2484 2059 2485 switch (uVersion) 2060 2486 { … … 2071 2497 rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields7[0]); 2072 2498 break; 2499 case 8: 2500 rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields8[0]); 2501 break; 2073 2502 default: 2074 2503 rc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; … … 2078 2507 { 2079 2508 rc = acpiR3RegisterPmHandlers(pThis); 2509 if (RT_FAILURE(rc)) 2510 return rc; 2511 rc = acpiR3RegisterSMBusHandlers(pThis); 2080 2512 if (RT_FAILURE(rc)) 2081 2513 return rc; … … 2861 3293 pThis->pfnAcpiPciConfigWrite(pPciDev, Address, u32Value, cb); 2862 3294 2863 /* PMREGMISC written */ 2864 if (Address == 0x80) 2865 { 3295 /* Assume that the base address is only changed when the corresponding 3296 * hardware functionality is disabled. The IO region is mapped when the 3297 * functionality is enabled by the guest. */ 3298 3299 if (Address == PMREGMISC) 3300 { 3301 RTIOPORT NewIoPortBase = 0; 2866 3302 /* Check Power Management IO Space Enable (PMIOSE) bit */ 2867 if (pPciDev->config[ 0x80] & 0x1)3303 if (pPciDev->config[PMREGMISC] & 0x01) 2868 3304 { 2869 RTIOPORT NewIoPortBase = (RTIOPORT)PCIDevGetDWord(pPciDev, 0x40);3305 NewIoPortBase = (RTIOPORT)PCIDevGetDWord(pPciDev, PMBA); 2870 3306 NewIoPortBase &= 0xffc0; 2871 2872 int rc = acpiR3UpdatePmHandlers(pThis, NewIoPortBase);2873 AssertRC(rc);2874 3307 } 3308 3309 int rc = acpiR3UpdatePmHandlers(pThis, NewIoPortBase); 3310 AssertRC(rc); 3311 } 3312 3313 if (Address == SMBHSTCFG) 3314 { 3315 RTIOPORT NewIoPortBase = 0; 3316 /* Check SMBus Controller Host Interface Enable (SMB_HST_EN) bit */ 3317 if (pPciDev->config[SMBHSTCFG] & SMBHSTCFG_SMB_HST_EN) 3318 { 3319 NewIoPortBase = (RTIOPORT)PCIDevGetDWord(pPciDev, SMBBA); 3320 NewIoPortBase &= 0xfff0; 3321 } 3322 3323 int rc = acpiR3UpdateSMBusHandlers(pThis, NewIoPortBase); 3324 AssertRC(rc); 2875 3325 } 2876 3326 … … 2991 3441 { 2992 3442 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 3443 3444 /* Play safe: make sure that the IRQ isn't stuck after a reset. */ 3445 acpiSetIrq(pThis, 0); 2993 3446 2994 3447 TMTimerLock(pThis->pPmTimerR3, VERR_IGNORED); … … 3006 3459 TMTimerUnlock(pThis->pPmTimerR3); 3007 3460 3008 /** @todo Should we really reset PM base? */ 3461 /* Real device behavior is resetting only the PM controller state, 3462 * but we're additionally doing the job of the BIOS. */ 3009 3463 acpiR3UpdatePmHandlers(pThis, PM_PORT_BASE); 3464 acpiR3PmPCIBIOSFake(pThis); 3465 3466 /* Reset SMBus base and PCI config space in addition to the SMBus controller 3467 * state. Real device behavior is only the SMBus controller state reset, 3468 * but we're additionally doing the job of the BIOS. */ 3469 acpiR3UpdateSMBusHandlers(pThis, SMB_PORT_BASE); 3470 acpiR3SMBusPCIBIOSFake(pThis); 3471 acpiR3SMBusResetDevice(pThis); 3010 3472 } 3011 3473 … … 3443 3905 } 3444 3906 3445 /* Set default port base */3907 /* Set default PM port base */ 3446 3908 pThis->uPmIoPortBase = PM_PORT_BASE; 3909 3910 /* Set default SMBus port base */ 3911 pThis->uSMBusIoPortBase = SMB_PORT_BASE; 3447 3912 3448 3913 /* … … 3477 3942 */ 3478 3943 rc = acpiR3RegisterPmHandlers(pThis); 3944 if (RT_FAILURE(rc)) 3945 return rc; 3946 3947 rc = acpiR3RegisterSMBusHandlers(pThis); 3479 3948 if (RT_FAILURE(rc)) 3480 3949 return rc; … … 3539 4008 PCIDevSetInterruptPin (&pThis->dev, 0x01); 3540 4009 3541 pThis->dev.config[0x40] = 0x01; /* PM base address, this bit marks it as IO range, not PA */ 3542 3543 #if 0 3544 int smb_io_base = 0xb100; 3545 dev->config[0x90] = smb_io_base | 1; /* SMBus base address */ 3546 dev->config[0x90] = smb_io_base >> 8; 3547 #endif 4010 Assert((pThis->uPmIoPortBase & 0x003f) == 0); 4011 acpiR3PmPCIBIOSFake(pThis); 4012 4013 Assert((pThis->uSMBusIoPortBase & 0x000f) == 0); 4014 acpiR3SMBusPCIBIOSFake(pThis); 4015 acpiR3SMBusResetDevice(pThis); 3548 4016 3549 4017 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->dev); … … 3558 4026 * Register the saved state. 3559 4027 */ 3560 rc = PDMDevHlpSSMRegister(pDevIns, 7, sizeof(*pThis), acpiR3SaveState, acpiR3LoadState);4028 rc = PDMDevHlpSSMRegister(pDevIns, 8, sizeof(*pThis), acpiR3SaveState, acpiR3LoadState); 3561 4029 if (RT_FAILURE(rc)) 3562 4030 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.