Changeset 44665 in vbox for trunk/src/VBox
- Timestamp:
- Feb 13, 2013 11:44:45 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83758
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp
r44647 r44665 2 2 /** @file 3 3 * DevIchIntelHD - VBox ICH Intel HD Audio Controller. 4 * 5 * @todo Exactly which datasheet PDF was used to produce this code? Would be 6 * great to know what to check the guest and emulation behavior against. 4 7 */ 5 8 … … 59 62 # error "Please specify your HDA device vendor/device IDs" 60 63 #endif 64 65 /** @todo r=bird: Looking at what the linux driver (accidentally?) does when 66 * updating CORBWP, I belive that the ICH6 spec is wrong and that CORBRP 67 * is read only except for bit 15. The bit 15 implementation is, btw., 68 * not according to Intel document number 301473-002, but not know 69 * exactly which document to check against, I might be mistaken 70 * here... */ 71 #define BIRD_THINKS_CORBRP_IS_MOSTLY_RO 61 72 62 73 #define HDA_NREGS 112 … … 529 540 DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm, 530 541 PHDASTREAMTRANSFERDESC pStreamDesc); 531 static int hdaMMIORegLookup(PHDASTATE pThis, uint32_t offReg);532 542 static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc); 533 543 #ifdef LOG_ENABLED … … 540 550 *******************************************************************************/ 541 551 /* see 302349 p 6.2*/ 542 static const struct 552 static const struct HDAREGDESC 543 553 { 544 554 /** Register offset in the register space. */ … … 558 568 /** Full name. */ 559 569 const char *name; 560 } g_a IchIntelHDRegMap[HDA_NREGS] =570 } g_aHdaRegMap[HDA_NREGS] = 561 571 { 562 572 /* offset size read mask write mask read callback write callback abbrev full name */ … … 579 589 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "CORBUBASE" , "CORB Upper Base Address" }, 580 590 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteCORBWP , "CORBWP" , "CORB Write Pointer" }, 591 #ifdef OLD_REGISTER_TABLE 581 592 { 0x0004A, 0x00002, 0x000000FF, 0x000080FF, hdaRegReadU8 , hdaRegWriteCORBRP , "CORBRP" , "CORB Read Pointer" }, 593 #else /** @todo 18.2.17 indicates that the 15th bit can be read as well as and written. hdaRegReadU8 is wrong, a special reader should be used. */ 594 { 0x0004A, 0x00002, 0x000080FF, 0x000080FF, hdaRegReadU16 , hdaRegWriteCORBRP , "CORBRP" , "CORB Read Pointer" }, 595 #endif 582 596 { 0x0004C, 0x00001, 0x00000003, 0x00000003, hdaRegReadU8 , hdaRegWriteCORBCTL , "CORBCTL" , "CORB Control" }, 583 597 { 0x0004D, 0x00001, 0x00000001, 0x00000001, hdaRegReadU8 , hdaRegWriteCORBSTS , "CORBSTS" , "CORB Status" }, … … 592 606 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "IC" , "Immediate Command" }, 593 607 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteUnimplemented, "IR" , "Immediate Response" }, 608 #ifdef OLD_REGISTER_TABLE 594 609 { 0x00068, 0x00004, 0x00000002, 0x00000002, hdaRegReadIRS , hdaRegWriteIRS , "IRS" , "Immediate Command Status" }, 610 #else /* 18.2.30 as well as the table says 16-bit. Linux accesses it as a 16-bit register. */ 611 { 0x00068, 0x00002, 0x00000002, 0x00000002, hdaRegReadIRS , hdaRegWriteIRS , "IRS" , "Immediate Command Status" }, 612 #endif 595 613 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32 , hdaRegWriteBase , "DPLBASE" , "DMA Position Lower Base" }, 596 614 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "DPUBASE" , "DMA Position Upper Base" }, … … 685 703 }; 686 704 705 /** 706 * HDA register aliases (HDA spec 3.3.45). 707 * @remarks Sorted by offReg. 708 */ 709 static const struct 710 { 711 /** The alias register offset. */ 712 uint32_t offReg; 713 /** The register index. */ 714 int idxAlias; 715 } g_aHdaRegAliases[] = 716 { 717 { 0x2084, HDA_REG_IND_NAME(SD0LPIB) }, 718 { 0x20a4, HDA_REG_IND_NAME(SD1LPIB) }, 719 { 0x20c4, HDA_REG_IND_NAME(SD2LPIB) }, 720 { 0x20e4, HDA_REG_IND_NAME(SD3LPIB) }, 721 { 0x2104, HDA_REG_IND_NAME(SD4LPIB) }, 722 { 0x2124, HDA_REG_IND_NAME(SD5LPIB) }, 723 { 0x2144, HDA_REG_IND_NAME(SD6LPIB) }, 724 { 0x2164, HDA_REG_IND_NAME(SD7LPIB) }, 725 }; 726 727 687 728 /** HDABDLEDESC field descriptors the v3+ saved state. */ 688 729 static SSMFIELD const g_aHdaBDLEDescFields[] = … … 714 755 }; 715 756 757 /** 758 * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff. 759 */ 760 static uint32_t const g_afMasks[5] = 761 { 762 UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0xffffff00), UINT32_C(0xffffffff) 763 }; 764 716 765 717 766 DECLINLINE(void) hdaUpdatePosBuf(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc) … … 761 810 } 762 811 763 static int hdaMMIORegLookup(PHDASTATE pThis, uint32_t offReg) 812 /** 813 * Looks up a register at the exact offset given by @a offReg. 814 * 815 * @returns Register index on success, -1 if not found. 816 * @param pThis The HDA device state. 817 * @param offReg The register offset. 818 */ 819 static int hdaRegLookup(PHDASTATE pThis, uint32_t offReg) 764 820 { 765 821 /* 766 * Aliases HDA spec 3.3.45 767 */ 768 switch (offReg) 769 { 770 case 0x2084: 771 return HDA_REG_IND_NAME(SD0LPIB); 772 case 0x20A4: 773 return HDA_REG_IND_NAME(SD1LPIB); 774 case 0x20C4: 775 return HDA_REG_IND_NAME(SD2LPIB); 776 case 0x20E4: 777 return HDA_REG_IND_NAME(SD3LPIB); 778 case 0x2104: 779 return HDA_REG_IND_NAME(SD4LPIB); 780 case 0x2124: 781 return HDA_REG_IND_NAME(SD5LPIB); 782 case 0x2144: 783 return HDA_REG_IND_NAME(SD6LPIB); 784 case 0x2164: 785 return HDA_REG_IND_NAME(SD7LPIB); 822 * Aliases. 823 */ 824 if (offReg >= g_aHdaRegAliases[0].offReg) 825 { 826 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++) 827 if (offReg == g_aHdaRegAliases[i].offReg) 828 return g_aHdaRegAliases[i].idxAlias; 829 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg); 830 return -1; 786 831 } 787 832 … … 789 834 * Binary search the 790 835 */ 791 int idx High = RT_ELEMENTS(g_aIchIntelHDRegMap);836 int idxEnd = RT_ELEMENTS(g_aHdaRegMap); 792 837 int idxLow = 0; 793 838 for (;;) 794 839 { 795 #ifdef DEBUG_vvl 796 Assert( idxHigh >= 0 797 && idxLow >= 0); 840 int idxMiddle = idxLow + (idxEnd - idxLow) / 2; 841 if (offReg < g_aHdaRegMap[idxMiddle].offset) 842 { 843 if (idxLow == idxMiddle) 844 break; 845 idxEnd = idxMiddle; 846 } 847 else if (offReg > g_aHdaRegMap[idxMiddle].offset) 848 { 849 idxLow = idxMiddle + 1; 850 if (idxLow >= idxEnd) 851 break; 852 } 853 else 854 return idxMiddle; 855 } 856 857 #ifdef RT_STRICT 858 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++) 859 Assert(g_aHdaRegMap[i].offset != offReg); 798 860 #endif 799 if ( idxHigh < idxLow 800 || idxHigh < 0) 801 break; 802 int idxMiddle = idxLow + (idxHigh - idxLow) / 2; 803 if (offReg < g_aIchIntelHDRegMap[idxMiddle].offset) 804 idxHigh = idxMiddle - 1; 805 else if (offReg >= g_aIchIntelHDRegMap[idxMiddle].offset + g_aIchIntelHDRegMap[idxMiddle].size) 806 idxLow = idxMiddle + 1; 807 else if ( offReg >= g_aIchIntelHDRegMap[idxMiddle].offset 808 && offReg < g_aIchIntelHDRegMap[idxMiddle].offset + g_aIchIntelHDRegMap[idxMiddle].size) 861 return -1; 862 } 863 864 /** 865 * Looks up a register covering the offset given by @a offReg. 866 * 867 * @returns Register index on success, -1 if not found. 868 * @param pThis The HDA device state. 869 * @param offReg The register offset. 870 */ 871 static int hdaRegLookupWithin(PHDASTATE pThis, uint32_t offReg) 872 { 873 /* 874 * Aliases. 875 */ 876 if (offReg >= g_aHdaRegAliases[0].offReg) 877 { 878 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++) 879 { 880 uint32_t off = offReg - g_aHdaRegAliases[i].offReg; 881 if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size) 882 return g_aHdaRegAliases[i].idxAlias; 883 } 884 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg); 885 return -1; 886 } 887 888 /* 889 * Binary search the 890 */ 891 int idxEnd = RT_ELEMENTS(g_aHdaRegMap); 892 int idxLow = 0; 893 for (;;) 894 { 895 int idxMiddle = idxLow + (idxEnd - idxLow) / 2; 896 if (offReg < g_aHdaRegMap[idxMiddle].offset) 897 { 898 if (idxLow == idxMiddle) 899 break; 900 idxEnd = idxMiddle; 901 } 902 else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size) 903 { 904 idxLow = idxMiddle + 1; 905 if (idxLow >= idxEnd) 906 break; 907 } 908 else 809 909 return idxMiddle; 810 910 } 911 912 #ifdef RT_STRICT 913 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++) 914 Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size); 915 #endif 811 916 return -1; 812 917 } 918 813 919 814 920 static int hdaCmdSync(PHDASTATE pThis, bool fLocal) … … 978 1084 static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 979 1085 { 980 Assert(((pThis->au32Regs[iReg] & g_a IchIntelHDRegMap[iReg].readable) & 0xffffff00) == 0);1086 Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0); 981 1087 return hdaRegReadU32(pThis, iReg, pu32Value); 982 1088 } … … 991 1097 static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 992 1098 { 993 Assert(((pThis->au32Regs[iReg] & g_a IchIntelHDRegMap[iReg].readable) & 0xffff0000) == 0);1099 Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0); 994 1100 return hdaRegReadU32(pThis, iReg, pu32Value); 995 1101 } … … 1004 1110 static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 1005 1111 { 1006 Assert(((pThis->au32Regs[iReg] & g_a IchIntelHDRegMap[iReg].readable) & 0xff000000) == 0);1112 Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0); 1007 1113 return hdaRegReadU32(pThis, iReg, pu32Value); 1008 1114 } … … 1017 1123 static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 1018 1124 { 1019 *pu32Value = pThis->au32Regs[iReg] & g_a IchIntelHDRegMap[iReg].readable;1125 *pu32Value = pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable; 1020 1126 return VINF_SUCCESS; 1021 1127 } … … 1023 1129 static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 1024 1130 { 1025 pThis->au32Regs[iReg] = (u32Value & g_a IchIntelHDRegMap[iReg].writable)1026 | (pThis->au32Regs[iReg] & ~g_a IchIntelHDRegMap[iReg].writable);1131 pThis->au32Regs[iReg] = (u32Value & g_aHdaRegMap[iReg].writable) 1132 | (pThis->au32Regs[iReg] & ~g_aHdaRegMap[iReg].writable); 1027 1133 return VINF_SUCCESS; 1028 1134 } … … 1115 1221 if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST)) 1116 1222 CORBRP(pThis) = 0; 1223 #ifndef BIRD_THINKS_CORBRP_IS_MOSTLY_RO 1117 1224 else 1118 1225 return hdaRegWriteU8(pThis, iReg, u32Value); 1226 #endif 1119 1227 return VINF_SUCCESS; 1120 1228 } … … 1926 2034 { 1927 2035 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 1928 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;1929 int idxReg = hdaMMIORegLookup(pThis, offReg);1930 2036 int rc; 1931 Assert(!(offReg & 3)); Assert(cb == 4); 2037 2038 /* 2039 * Look up and log. 2040 */ 2041 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr; 2042 int idxReg = hdaRegLookup(pThis, offReg); 2043 #ifdef LOG_ENABLED 2044 unsigned const cbLog = cb; 2045 uint32_t offRegLog = offReg; 2046 #endif 2047 2048 Log(("hdaMMIORead: offReg=%#x cb=%#x\n", offReg, cb)); 2049 #define NEW_READ_CODE 2050 #ifdef NEW_READ_CODE 2051 Assert(cb == 4); Assert((offReg & 3) == 0); 1932 2052 1933 2053 if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL) … … 1939 2059 if (idxReg != -1) 1940 2060 { 1941 rc = g_aIchIntelHDRegMap[idxReg].pfnRead(pThis, idxReg, (uint32_t *)pv); 1942 Log(("hda: read %s[%x/%x]\n", g_aIchIntelHDRegMap[idxReg].abbrev, *(uint32_t *)pv)); 2061 /* ASSUMES gapless DWORD at end of map. */ 2062 if (g_aHdaRegMap[idxReg].size == 4) 2063 { 2064 /* 2065 * Straight forward DWORD access. 2066 */ 2067 rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, (uint32_t *)pv); 2068 Log(("hda: read %s => %x (%Rrc)\n", g_aHdaRegMap[idxReg].abbrev, *(uint32_t *)pv, rc)); 2069 } 2070 else 2071 { 2072 /* 2073 * Multi register read (unless there are trailing gaps). 2074 * ASSUMES that only DWORD reads have sideeffects. 2075 */ 2076 uint32_t u32Value = 0; 2077 unsigned cbLeft = 4; 2078 do 2079 { 2080 uint32_t const cbReg = g_aHdaRegMap[idxReg].size; 2081 uint32_t u32Tmp = 0; 2082 2083 rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, &u32Tmp); 2084 Log(("hda: read %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxReg].abbrev, cbReg, *(uint32_t *)pv, rc)); 2085 if (rc != VINF_SUCCESS) 2086 break; 2087 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8); 2088 2089 cbLeft -= cbReg; 2090 offReg += cbReg; 2091 idxReg++; 2092 } while (cbLeft > 0 && g_aHdaRegMap[idxReg].offset == offReg); 2093 2094 if (rc == VINF_SUCCESS) 2095 *(uint32_t *)pv = u32Value; 2096 else 2097 Assert(!IOM_SUCCESS(rc)); 2098 } 1943 2099 } 1944 2100 else … … 1947 2103 Log(("hda: hole at %x is accessed for read\n", offReg)); 1948 2104 } 2105 #else 2106 if (idxReg != -1) 2107 { 2108 /** @todo r=bird: Accesses crossing register boundraries aren't handled 2109 * right from what I can tell? If they are, please explain 2110 * what the rules are. */ 2111 uint32_t mask = 0; 2112 uint32_t shift = (g_aHdaRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8; 2113 uint32_t u32Value = 0; 2114 switch(cb) 2115 { 2116 case 1: mask = 0x000000ff; break; 2117 case 2: mask = 0x0000ffff; break; 2118 case 4: 2119 /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */ 2120 case 8: 2121 mask = 0xffffffff; 2122 cb = 4; 2123 break; 2124 } 2125 #if 0 2126 /* Cross-register access. Mac guest hits this assert doing assumption 4 byte access to 3 byte registers e.g. {I,O}SDnCTL 2127 */ 2128 //Assert((cb <= g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset))); 2129 if (cb > g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset)) 2130 { 2131 int off = cb - (g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset)); 2132 rc = hdaMMIORead(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off); 2133 if (RT_FAILURE(rc)) 2134 AssertRCReturn (rc, rc); 2135 } 2136 //Assert(((offReg - g_aHdaRegMap[idxReg].offset) == 0)); 2137 #endif 2138 mask <<= shift; 2139 rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, &u32Value); 2140 *(uint32_t *)pv |= (u32Value & mask); 2141 Log(("hda: read %s[%x/%x]\n", g_aHdaRegMap[idxReg].abbrev, u32Value, *(uint32_t *)pv)); 2142 } 2143 else 2144 { 2145 *(uint32_t *)pv = 0xFF; 2146 Log(("hda: hole at %x is accessed for read\n", offReg)); 2147 rc = VINF_SUCCESS; 2148 } 2149 #endif 2150 2151 /* 2152 * Log the outcome. 2153 */ 2154 if (cbLog == 4) 2155 Log(("hdaMMIORead: @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc)); 2156 else if (cbLog == 2) 2157 Log(("hdaMMIORead: @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc)); 2158 else if (cbLog == 1) 2159 Log(("hdaMMIORead: @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc)); 2160 return rc; 2161 } 2162 2163 2164 DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxReg, uint32_t u32Value, char const *pszLog) 2165 { 2166 if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL) 2167 Log(("hda: access to registers except GCTL is blocked while reset\n")); /** @todo where is this enforced? */ 2168 2169 #ifdef LOG_ENABLED 2170 uint32_t const u32CurValue = pThis->au32Regs[idxReg]; 2171 #endif 2172 int rc = g_aHdaRegMap[idxReg].pfnWrite(pThis, idxReg, u32Value); 2173 Log(("hda: write %#x -> %s[%db]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxReg].abbrev, 2174 g_aHdaRegMap[idxReg].size, u32CurValue, pThis->au32Regs[idxReg], pszLog)); 1949 2175 return rc; 1950 2176 } … … 1956 2182 PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 1957 2183 { 1958 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 2184 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 2185 int rc; 2186 2187 /* 2188 * The behavior of accesses that aren't aligned on natural boundraries is 2189 * undefined. Just reject them out right. 2190 */ 2191 /** @todo IOM could check this, it could also split the 8 byte accesses for us. */ 2192 Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8); 2193 if (GCPhysAddr & (cb - 1)) 2194 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb); 2195 2196 /* 2197 * Lookup and log the access. 2198 */ 1959 2199 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr; 1960 int idxReg = hdaMMIORegLookup(pThis, offReg); 1961 int rc; 1962 Assert(!(offReg & 3)); Assert(cb == 4); 1963 1964 if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL) 1965 Log(("hda: access to registers except GCTL is blocked while reset\n")); 1966 2200 int idxReg = hdaRegLookup(pThis, offReg); 2201 uint64_t u64Value; 2202 if (cb == 4) u64Value = *(uint32_t const *)pv; 2203 else if (cb == 2) u64Value = *(uint16_t const *)pv; 2204 else if (cb == 1) u64Value = *(uint8_t const *)pv; 2205 else if (cb == 8) u64Value = *(uint64_t const *)pv; 2206 else 2207 AssertReleaseMsgFailed(("%d\n", cb)); 2208 2209 #ifdef LOG_ENABLED 2210 uint32_t const u32LogOldValue = idxReg != -1 ? pThis->au32Regs[idxReg] : UINT32_MAX; 2211 uint32_t const offRegLog = offReg; 2212 int const idxRegLog = idxReg; 2213 if (idxReg == -1) 2214 Log(("hdaMMIOWrite: @%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb)); 2215 else if (cb == 4) 2216 Log(("hdaMMIOWrite: @%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev)); 2217 else if (cb == 2) 2218 Log(("hdaMMIOWrite: @%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev)); 2219 else if (cb == 1) 2220 Log(("hdaMMIOWrite: @%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev)); 2221 if (idxReg != -1 && g_aHdaRegMap[idxReg].size != cb) 2222 Log(("hdaMMIOWrite: size=%d != cb=%d!!\n", g_aHdaRegMap[idxReg].size, cb)); 2223 #endif 2224 2225 #define NEW_WRITE_CODE 2226 #ifdef NEW_WRITE_CODE 2227 /* 2228 * Try for a direct hit first. 2229 */ 2230 if (idxReg != -1 && g_aHdaRegMap[idxReg].size == cb) 2231 rc = hdaWriteReg(pThis, idxReg, u64Value, ""); 2232 /* 2233 * Partial or multiple register access, loop thru the requested memory. 2234 */ 2235 else 2236 { 2237 /* If it's an access beyond the start of the register, shift the input 2238 value and fill in missing bits. Natural alignment rules means we 2239 will only see 1 or 2 byte accesses of this kind, so no risk of 2240 shifting out input values. */ 2241 if (idxReg == -1 && (idxReg = hdaRegLookupWithin(pThis, offReg)) != -1) 2242 { 2243 uint32_t const cbBefore = g_aHdaRegMap[idxReg].offset - offReg; Assert(cbBefore > 0 && cbBefore < 4); 2244 offReg -= cbBefore; 2245 u64Value <<= cbBefore * 8; 2246 u64Value |= pThis->au32Regs[idxReg] & g_afMasks[cbBefore]; 2247 Log(("hdaMMIOWrite: Within register, supplied %u leading bits: %#llx -> %#llx ...\n", 2248 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value)); 2249 } 2250 2251 /* Loop thru the write area, it may covert multiple registers. */ 2252 rc = VINF_SUCCESS; 2253 for (;;) 2254 { 2255 uint32_t cbReg; 2256 if (idxReg != -1) 2257 { 2258 cbReg = g_aHdaRegMap[idxReg].size; 2259 if (cb < cbReg) 2260 { 2261 u64Value |= pThis->au32Regs[idxReg] & g_afMasks[cbReg] & ~g_afMasks[cb]; 2262 Log(("hdaMMIOWrite: Supplying missing bits (%#x): %#llx -> %#llx ...\n", 2263 g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value)); 2264 } 2265 rc = hdaWriteReg(pThis, idxReg, u64Value, "*"); 2266 } 2267 else 2268 { 2269 LogRel(("hda: Invalid write access @0x%x!\n", offReg)); 2270 cbReg = 1; 2271 } 2272 if (cbReg >= cb) 2273 break; 2274 2275 /* advance */ 2276 offReg += cbReg; 2277 cb -= cbReg; 2278 u64Value >>= cbReg * 8; 2279 if (idxReg == -1) 2280 idxReg = hdaRegLookup(pThis, offReg); 2281 else 2282 { 2283 idxReg++; 2284 if ( (unsigned)idxReg >= RT_ELEMENTS(g_aHdaRegMap) 2285 || g_aHdaRegMap[idxReg].offset != offReg) 2286 idxReg = -1; 2287 } 2288 } 2289 } 2290 #else 1967 2291 if (idxReg != -1) 1968 2292 { 1969 #ifdef LOG_ENABLED 1970 uint32_t const u32CurValue = pThis->au32Regs[idxReg]; 2293 /** @todo r=bird: This looks like code for handling unaligned register 2294 * accesses. If it isn't, then add a comment explaining what you're 2295 * trying to do here. OTOH, if it is then it has the following 2296 * issues: 2297 * -# You're calculating the wrong new value for the register. 2298 * -# You're not handling cross register accesses. Imagine a 2299 * 4-byte write starting at CORBCTL, or a 8-byte write. 2300 * 2301 * PS! consider dropping the 'offset' argument to pfnWrite/pfnRead as 2302 * nobody seems to be using it and it just adds complexity when reading 2303 * the code. 2304 * 2305 */ 2306 uint32_t u32CurValue = pThis->au32Regs[idxReg]; 2307 uint32_t u32NewValue; 2308 uint32_t mask; 2309 switch (cb) 2310 { 2311 case 1: 2312 u32NewValue = *(uint8_t const *)pv; 2313 mask = 0xff; 2314 break; 2315 case 2: 2316 u32NewValue = *(uint16_t const *)pv; 2317 mask = 0xffff; 2318 break; 2319 case 4: 2320 case 8: 2321 /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */ 2322 u32NewValue = *(uint32_t const *)pv; 2323 mask = 0xffffffff; 2324 cb = 4; 2325 break; 2326 default: 2327 AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* shall not happen. */ 2328 } 2329 /* cross-register access, see corresponding comment in hdaMMIORead */ 2330 uint32_t shift = (g_aHdaRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8; 2331 mask <<= shift; 2332 u32NewValue <<= shift; 2333 u32NewValue &= mask; 2334 u32NewValue |= (u32CurValue & ~mask); 2335 2336 rc = g_aHdaRegMap[idxReg].pfnWrite(pThis, idxReg, u32NewValue); 2337 Log(("hda: write %s:(%x) %x => %x\n", g_aHdaRegMap[idxReg].abbrev, u32NewValue, 2338 u32CurValue, pThis->au32Regs[idxReg])); 2339 } 2340 else 2341 rc = VINF_SUCCESS; 1971 2342 #endif 1972 rc = g_aIchIntelHDRegMap[idxReg].pfnWrite(pThis, idxReg, *(uint32_t const *)pv); 1973 Log(("hda: write %s:(%x) %x => %x\n", g_aIchIntelHDRegMap[idxReg].abbrev, *(uint32_t const *)pv, 1974 u32CurValue, pThis->au32Regs[idxReg])); 1975 } 1976 else 1977 { 1978 LogRel(("hda: Invalid write access @0x%x\n", offReg)); 1979 rc = VINF_SUCCESS; 1980 } 1981 1982 Log(("hda: hole at %x is accessed for write\n", offReg)); 2343 Log(("hdaMMIOWrite: @%#05x %#x -> %#x\n", offRegLog, u32LogOldValue, 2344 idxRegLog != -1 ? pThis->au32Regs[idxRegLog] : UINT32_MAX)); 1983 2345 return rc; 1984 2346 } … … 1998 2360 int rc; 1999 2361 2000 /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */ 2362 /* 2363 * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word. 2364 * 2365 * Let IOM talk DWORDs when reading, saves a lot of complications. On 2366 * writing though, we have to do it all ourselves because of sideeffects. 2367 */ 2001 2368 Assert(enmType == PCI_ADDRESS_SPACE_MEM); 2002 2369 rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, NULL /*pvUser*/, 2003 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING, 2370 #ifdef NEW_READ_CODE 2371 IOMMMIO_FLAGS_READ_DWORD | 2372 #else 2373 IOMMMIO_FLAGS_READ_PASSTHRU | 2374 #endif 2375 IOMMMIO_FLAGS_WRITE_PASSTHRU, 2004 2376 hdaMMIOWrite, hdaMMIORead, "ICH6_HDA"); 2005 2377 … … 2220 2592 int iReg = 0; 2221 2593 for (; iReg < HDA_NREGS; ++iReg) 2222 if (!RTStrICmp(g_a IchIntelHDRegMap[iReg].abbrev, pszArgs))2594 if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs)) 2223 2595 return iReg; 2224 2596 return -1; … … 2231 2603 && iHdaIndex >= 0 2232 2604 && iHdaIndex < HDA_NREGS); 2233 pHlp->pfnPrintf(pHlp, "hda: %s: 0x%x\n", g_a IchIntelHDRegMap[iHdaIndex].abbrev, pThis->au32Regs[iHdaIndex]);2605 pHlp->pfnPrintf(pHlp, "hda: %s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[iHdaIndex]); 2234 2606 } 2235 2607 … … 2602 2974 AssertRC(rc); 2603 2975 #endif 2976 2977 /* 2978 * Some debug assertions. 2979 */ 2980 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++) 2981 { 2982 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i]; 2983 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL; 2984 2985 /* binary search order. */ 2986 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset, 2987 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 2988 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size)); 2989 2990 /* alignment. */ 2991 AssertReleaseMsg( pReg->size == 1 2992 || (pReg->size == 2 && (pReg->offset & 1) == 0) 2993 || (pReg->size == 3 && (pReg->offset & 3) == 0) 2994 || (pReg->size == 4 && (pReg->offset & 3) == 0), 2995 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 2996 2997 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */ 2998 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg); 2999 if (pReg->offset & 3) 3000 { 3001 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL; 3002 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 3003 if (pPrevReg) 3004 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset, 3005 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 3006 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size)); 3007 } 3008 #if 0 3009 if ((pReg->offset + pReg->size) & 3) 3010 { 3011 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 3012 if (pNextReg) 3013 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset, 3014 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 3015 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size)); 3016 } 3017 #endif 3018 3019 /* The final entry is a full dword, no gaps! Allows shortcuts. */ 3020 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0, 3021 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 3022 } 2604 3023 2605 3024 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.