- Timestamp:
- Jun 28, 2011 6:02:23 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp
r37642 r37654 54 54 55 55 PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb); 56 PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);56 PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb); 57 57 static DECLCALLBACK(void) hdaReset (PPDMDEVINS pDevIns); 58 58 … … 535 535 536 536 static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc); 537 static int hda Lookup(INTELHDLinkState* pState, uint32_t u32Offset);537 static int hdaMMIORegLookup(INTELHDLinkState* pState, uint32_t u32Offset); 538 538 static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc); 539 539 #ifdef LOG_ENABLED … … 733 733 } 734 734 735 static int hda Lookup(INTELHDLinkState* pState, uint32_t u32Offset)735 static int hdaMMIORegLookup(INTELHDLinkState* pState, uint32_t u32Offset) 736 736 { 737 737 int idxMiddle; 738 738 int idxHigh = RT_ELEMENTS(s_ichIntelHDRegMap); 739 739 int idxLow = 0; 740 while (1)741 {742 if (idxHigh < idxLow)743 break;744 idxMiddle = idxLow + (idxHigh - idxLow)/2;745 if (u32Offset < s_ichIntelHDRegMap[idxMiddle].offset)746 {747 idxHigh = idxMiddle - 1;748 continue;749 }750 if (u32Offset >= s_ichIntelHDRegMap[idxMiddle].offset + s_ichIntelHDRegMap[idxMiddle].size)751 {752 idxLow = idxMiddle + 1;753 continue;754 }755 if (u32Offset >= s_ichIntelHDRegMap[idxMiddle].offset756 && u32Offset < s_ichIntelHDRegMap[idxMiddle].offset + s_ichIntelHDRegMap[idxMiddle].size)757 return idxMiddle;758 }759 740 /* Aliases HDA spec 3.3.45 */ 760 741 switch(u32Offset) … … 776 757 case 0x2164: 777 758 return HDA_REG_IND_NAME(SD7LPIB); 759 } 760 while (1) 761 { 762 #ifdef DEBUG_vvl 763 Assert(( idxHigh >= 0 764 && idxLow >= 0)); 765 #endif 766 if ( idxHigh < idxLow 767 || idxHigh < 0) 768 break; 769 idxMiddle = idxLow + (idxHigh - idxLow)/2; 770 if (u32Offset < s_ichIntelHDRegMap[idxMiddle].offset) 771 { 772 idxHigh = idxMiddle - 1; 773 continue; 774 } 775 if (u32Offset >= s_ichIntelHDRegMap[idxMiddle].offset + s_ichIntelHDRegMap[idxMiddle].size) 776 { 777 idxLow = idxMiddle + 1; 778 continue; 779 } 780 if ( u32Offset >= s_ichIntelHDRegMap[idxMiddle].offset 781 && u32Offset < s_ichIntelHDRegMap[idxMiddle].offset + s_ichIntelHDRegMap[idxMiddle].size) 782 return idxMiddle; 778 783 } 779 784 return -1; … … 1870 1875 int rc = VINF_SUCCESS; 1871 1876 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *); 1872 uint32_t u32Offset= GCPhysAddr - pThis->hda.addrMMReg;1873 int i ndex = hdaLookup(&pThis->hda, u32Offset);1874 if (pThis->hda.fInReset && i ndex!= ICH6_HDA_REG_GCTL)1877 uint32_t offReg = GCPhysAddr - pThis->hda.addrMMReg; 1878 int idxReg = hdaMMIORegLookup(&pThis->hda, offReg); 1879 if (pThis->hda.fInReset && idxReg != ICH6_HDA_REG_GCTL) 1875 1880 Log(("hda: access to registers except GCTL is blocked while reset\n")); 1876 1881 1877 if ( index == -1 1878 || cb > 4) 1879 LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", u32Offset, cb)); 1880 1881 if (index != -1) 1882 if (idxReg == -1) 1883 LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", offReg, cb)); 1884 1885 if (idxReg != -1) 1882 1886 { 1883 1887 /** @todo r=bird: Accesses crossing register boundraries aren't handled … … 1885 1889 * what the rules are. */ 1886 1890 uint32_t mask = 0; 1887 uint32_t shift = ( u32Offset - s_ichIntelHDRegMap[index].offset) % sizeof(uint32_t) * 8;1888 uint32_t v= 0;1891 uint32_t shift = (s_ichIntelHDRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8; 1892 uint32_t u32Value = 0; 1889 1893 switch(cb) 1890 1894 { 1891 1895 case 1: mask = 0x000000ff; break; 1892 1896 case 2: mask = 0x0000ffff; break; 1893 case 3: mask = 0x00ffffff; break; 1894 case 4: mask = 0xffffffff; break; 1897 case 4: 1898 /* 18.2 of ICH6 datasheet defines wideness of the accesses byte, word and double word */ 1899 case 8: 1900 mask = 0xffffffff; 1901 cb = 4; 1902 break; 1895 1903 } 1904 #if 0 1905 /* cross register access. Mac guest hit this assert doing assumption 4 byte access to 3 byte registers e.g. {I,O}SDnCTL 1906 */ 1907 //Assert((cb <= s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset))); 1908 if (cb > s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset)) 1909 { 1910 int off = cb - (s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset)); 1911 rc = hdaMMIORead(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off); 1912 if (RT_FAILURE(rc)) 1913 AssertRCReturn (rc, rc); 1914 } 1915 //Assert(((offReg - s_ichIntelHDRegMap[idxReg].offset) == 0)); 1916 #endif 1896 1917 mask <<= shift; 1897 rc = s_ichIntelHDRegMap[i ndex].pfnRead(&pThis->hda, u32Offset, index, &v);1898 *(uint32_t *)pv = (v & mask) >> shift;1899 Log(("hda: read %s[%x/%x]\n", s_ichIntelHDRegMap[i ndex].abbrev, v, *(uint32_t *)pv));1918 rc = s_ichIntelHDRegMap[idxReg].pfnRead(&pThis->hda, offReg, idxReg, &u32Value); 1919 *(uint32_t *)pv |= (u32Value & mask); 1920 Log(("hda: read %s[%x/%x]\n", s_ichIntelHDRegMap[idxReg].abbrev, u32Value, *(uint32_t *)pv)); 1900 1921 return rc; 1901 1922 } 1902 1923 *(uint32_t *)pv = 0xFF; 1903 Log(("hda: hole at %x is accessed for read\n", u32Offset));1924 Log(("hda: hole at %x is accessed for read\n", offReg)); 1904 1925 return rc; 1905 1926 } … … 1922 1943 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *); 1923 1944 uint32_t offReg = GCPhysAddr - pThis->hda.addrMMReg; 1924 int idxReg = hda Lookup(&pThis->hda, offReg);1945 int idxReg = hdaMMIORegLookup(&pThis->hda, offReg); 1925 1946 int rc = VINF_SUCCESS; 1926 1947 … … 1946 1967 * the code. 1947 1968 * 1948 * PPS. 'v' is not a very good variable name.1949 * PPPS. We don't do 3 byte writes, only 1, 2, 4 and 8.1950 1969 */ 1951 1970 uint32_t u32CurValue = pThis->hda.au32Regs[idxReg]; … … 1956 1975 case 1: 1957 1976 u32NewValue = *(uint8_t const *)pv; 1958 mask = 0xff ffff00;1977 mask = 0xff; 1959 1978 break; 1960 1979 case 2: 1961 1980 u32NewValue = *(uint16_t const *)pv; 1962 mask = 0xffff 0000;1981 mask = 0xffff; 1963 1982 break; 1964 1983 case 4: 1965 case 8: /** @todo r=bird: Add a line about why 8-byte accesses are handled like 4-byte ones. */ 1984 case 8: 1985 /* 18.2 of ICH6 datasheet defines wideness of the accesses byte, word and double word */ 1966 1986 u32NewValue = *(uint32_t const *)pv; 1967 mask = 0; 1987 mask = 0xffffffff; 1988 cb = 4; 1968 1989 break; 1969 1990 default: 1970 1991 AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* shall not happen. */ 1971 1992 } 1972 uint32_t shift = (offReg - s_ichIntelHDRegMap[idxReg].offset) % sizeof(uint32_t) * 8; 1993 /* cross register access, see corresponding comment in hdaMMIORead */ 1994 #if 0 1995 if (cb > s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset)) 1996 { 1997 int off = cb - (s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset)); 1998 rc = hdaMMIOWrite(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off); 1999 if (RT_FAILURE(rc)) 2000 AssertRCReturn (rc, rc); 2001 } 2002 #endif 2003 uint32_t shift = (s_ichIntelHDRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8; 1973 2004 mask <<= shift; 1974 u32NewValue = ((u32CurValue & mask) | (u32NewValue & ~mask)) >> shift; 2005 u32NewValue <<= shift; 2006 u32NewValue &= mask; 2007 u32NewValue |= (u32CurValue & ~mask); 1975 2008 1976 2009 rc = s_ichIntelHDRegMap[idxReg].pfnWrite(&pThis->hda, offReg, idxReg, u32NewValue);
Note:
See TracChangeset
for help on using the changeset viewer.