tstOhciRegisterAccess.cpp revision c7a877c301dd99550c6d2e59bd4483c02bb08959
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync/* $Id$ */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync/** @file
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * tstOhciRegisterAccess - OHCI Register Access Tests / Experiments.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync/*
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * Copyright (C) 2011 Oracle Corporation
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync *
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * available from http://www.virtualbox.org. This file is free software;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * General Public License (GPL) as published by the Free Software
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync/*******************************************************************************
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync* Header Files *
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync*******************************************************************************/
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <VBox/log.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <iprt/mem.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <iprt/memobj.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <iprt/string.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <iprt/asm-amd64-x86.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <iprt/param.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#include <VBox/sup.h>
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#undef LogRel
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync#define LogRel(a) SUPR0Printf a
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync/*******************************************************************************
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync* Global Variables *
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync*******************************************************************************/
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync/** Register names. */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsyncstatic const char * const g_apszRegNms[] =
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync{
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRevision",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcControl",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcCommandStatus",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcInterruptStatus",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcInterruptEnable",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcInterruptDisable",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcHCCA",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcPeriodCurrentED",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcControlHeadED",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcControlCurrentED",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcBulkHeadED",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcBulkCurrentED",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcDoneHead",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcFmInterval",
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcFmRemaining",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcFmNumber",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcPeriodicStart",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcLSThreshold",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhDescriptorA",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhDescriptorB",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhStatus",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /* Variable number of root hub ports: */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[0]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[1]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[2]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[3]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[4]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[5]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[6]",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "HcRhPortStatus[7]"
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync};
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsyncstatic bool TestOhciWrites(RTVPTRUNION uPtr)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync{
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync static struct
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync {
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync unsigned iReg;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uint32_t uVal1;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uint32_t uVal2;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync } const s_aRegs[] =
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync {
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync { 13 /* HcFmInterval */, 0x58871120, 0 }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync };
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync bool fSuccess = true;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_aRegs); i++)
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync {
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uint32_t const iReg = s_aRegs[i].iReg;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync RTVPTRUNION uPtrReg;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uPtrReg.pu32 = &uPtr.pu32[iReg];
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uint32_t uInitialValue = *uPtrReg.pu32;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync LogRel(("TestOhciWrites: %p iReg=%2d %20s = %08RX32\n", uPtrReg.pv, iReg, g_apszRegNms[iReg], uInitialValue));
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync bool fDone = true;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync const char *pszError = NULL;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync RTCCUINTREG const fFlags = ASMIntDisableFlags();
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync /*
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync * DWORD writes.
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync */
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uInitialValue = *uPtrReg.pu32;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync *uPtrReg.pu32 = uInitialValue;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uint32_t u32A = *uPtrReg.pu32;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync uint32_t const uChangedValue = s_aRegs[i].uVal1 != uInitialValue ? s_aRegs[i].uVal1 : s_aRegs[i].uVal2;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync if (u32A == uInitialValue)
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync {
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync /* Change the value. */
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync *uPtrReg.pu32 = uChangedValue;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync u32A = *uPtrReg.pu32;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync *uPtrReg.pu32 = uInitialValue;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync if (u32A != uChangedValue)
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync pszError = "Writing changed value failed";
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync else
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync {
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync u32A = *uPtrReg.pu32;
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync if (u32A != uInitialValue)
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync pszError = "Restore error 1";
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync else
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync pszError = "Writing back initial value failed";
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync /*
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync * Write byte changes.
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync */
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync for (unsigned iByte = 0; !pszError && iByte < 4; iByte)
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync {
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync /* Change the value. */
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync uPtrReg.pu8[iByte] = (uint8_t)(uChangedValue >> iByte * 8);
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync u32A = *uPtrReg.pu32;
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync *uPtrReg.pu32 = uInitialValue;
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync if (u32A != (uChangedValue & UINT32_C(0xff) << iByte * 8))
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync {
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync static const char * const s_apsz[] = { "byte 0", "byte 1", "byte 2", "byte 3" };
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync pszError = s_apsz[iByte];
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync }
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync else
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync {
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync u32A = *uPtrReg.pu32;
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync if (u32A != uInitialValue)
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync pszError = "Restore error 2";
c7a877c301dd99550c6d2e59bd4483c02bb08959vboxsync }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync *uPtrReg.pu32 = uInitialValue;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync ASMSetFlags(fFlags);
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync ASMNopPause();
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync /*
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync * Complain on failure.
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync */
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync if (!fDone)
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync LogRel(("TestOhciWrites: Warning! Register %s was never stable enough for testing! %08RX32 %08RX32 %08RX32\n",
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync g_apszRegNms[iReg], uInitialValue, u32A, uChangedValue, uInitialValue));
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync else if (pszError)
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync {
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync LogRel(("TestOhciWrites: Error! Register %s failed: %s; uInitialValue=%08RX32 uChangedValue=%08RX32 u32A=%08RX32\n",
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync g_apszRegNms[iReg], pszError, uInitialValue, uChangedValue, u32A));
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync fSuccess = false;
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync }
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync
f94dcbf4d4de095572e91b9475d65a68c18ab92avboxsync return fSuccess;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync}
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsyncstatic bool TestOhciReads(RTVPTRUNION uPtr)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync{
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /*
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * We can read just about any register we like since read shouldn't have
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * any side effects. However, some registers are volatile and makes for
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * difficult targets, thus the ugly code.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync bool fSuccess = true;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uint32_t cMaxReg = RT_ELEMENTS(g_apszRegNms);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync for (uint32_t iReg = 0; iReg < cMaxReg; iReg++, uPtr.pu32++)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync const char *pszError = NULL;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync bool fDone = false;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uint32_t uInitialValue = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uint32_t u32A = 0;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uint32_t u32B = 0;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uint32_t u32C = 0;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("TestOhciReads: %p iReg=%2d %20s = %08RX32\n", uPtr.pv, iReg, g_apszRegNms[iReg], uInitialValue));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync for (uint32_t iTry = 0; !fDone && iTry < 1024; iTry++)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync pszError = NULL;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fDone = true;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32A = u32B = u32C = 0;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync RTCCUINTREG const fFlags = ASMIntDisableFlags();
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uInitialValue = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /* Test byte access. */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync for (unsigned iByte = 0; iByte < 4; iByte++)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32A = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B = uPtr.pu8[iByte];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32C = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32A != uInitialValue || u32C != uInitialValue)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fDone = false;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync static uint32_t const a_au32Masks[] =
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync UINT32_C(0xffffff00), UINT32_C(0xffff00ff), UINT32_C(0xff00ffff), UINT32_C(0x00ffffff)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync };
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B <<= iByte * 8;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B |= uInitialValue & a_au32Masks[iByte];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32B != uInitialValue)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync static const char * const s_apsz[] = { "byte 0", "byte 1", "byte 2", "byte 3" };
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync pszError = s_apsz[iByte];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /* Test aligned word access. */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (fDone)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync for (unsigned iWord = 0; iWord < 2; iWord++)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32A = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B = uPtr.pu16[iWord];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32C = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32A != uInitialValue || u32C != uInitialValue)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fDone = false;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B <<= iWord * 16;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B |= uInitialValue & (iWord == 0 ? UINT32_C(0xffff0000) : UINT32_C(0x0000ffff));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32B != uInitialValue)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync pszError = iWord == 0 ? "aligned word 0 access" : "aligned word 1 access";
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /* Test unaligned word access. */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (fDone)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync for (int iWord = ((uintptr_t)uPtr.pv & PAGE_OFFSET_MASK) == 0; iWord < 3; iWord++)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32A = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B = *(volatile uint16_t *)&uPtr.pu8[iWord * 2 - 1];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32C = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32A != uInitialValue || u32C != uInitialValue)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fDone = false;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync switch (iWord)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 0: u32B = (u32B >> 8) | (u32A & UINT32_C(0xffffff00)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 1: u32B = (u32B << 8) | (u32A & UINT32_C(0xff0000ff)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 2: u32B = (u32B << 24) | (u32A & UINT32_C(0x00ffffff)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32B != u32A)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync static const char * const s_apsz[] = { "unaligned word 0", "unaligned word 1", "unaligned word 2" };
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync pszError = s_apsz[iWord];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /* Test unaligned dword access. */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (fDone)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync for (int iByte = ((uintptr_t)uPtr.pv & PAGE_OFFSET_MASK) == 0 ? 0 : -3; iByte < 4; iByte++)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32A = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32B = *(volatile uint32_t *)&uPtr.pu8[iByte];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync u32C = *uPtr.pu32;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32A != uInitialValue || u32C != uInitialValue)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fDone = false;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync switch (iByte)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case -3: u32B = (u32B >> 24) | (uInitialValue & UINT32_C(0xffffff00)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case -2: u32B = (u32B >> 16) | (uInitialValue & UINT32_C(0xffff0000)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case -1: u32B = (u32B >> 8) | (uInitialValue & UINT32_C(0xff000000)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 0: break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 1: u32B = (u32B << 8) | (uInitialValue & UINT32_C(0x000000ff)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 2: u32B = (u32B << 16) | (uInitialValue & UINT32_C(0x0000ffff)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync case 3: u32B = (u32B << 24) | (uInitialValue & UINT32_C(0x00ffffff)); break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (u32B != u32A)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync static const char * const s_apsz[] =
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "unaligned dword -3", "unaligned dword -2", "unaligned dword -1",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync "unaligned dword 0", "unaligned dword 1", "unaligned dword 2", "unaligned dword 3"
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync };
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync pszError = s_apsz[iByte + 3];
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync break;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync ASMSetFlags(fFlags);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync ASMNopPause();
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync } /* try loop */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /*
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * Complain on failure.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (!fDone)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("TestOhciReads: Warning! Register %s was never stable enough for testing! %08RX32 %08RX32 %08RX32\n",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync g_apszRegNms[iReg], uInitialValue, u32A, u32C));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync else if (pszError)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("TestOhciReads: Error! Register %s failed: %s; uInitialValue=%08RX32 u32B=%08RX32\n",
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync g_apszRegNms[iReg], pszError, uInitialValue, u32B));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fSuccess = false;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync return fSuccess;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync}
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsyncint tstOhciRegisterAccess(RTHCPHYS HCPhysOHCI)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync{
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: HCPhysOHCI=%RHp\n", HCPhysOHCI));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /*
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * Map the OHCI registers so we can access them.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync RTR0MEMOBJ hMemObj;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync int rc = RTR0MemObjEnterPhys(&hMemObj, HCPhysOHCI, PAGE_SIZE, RTMEM_CACHE_POLICY_MMIO);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (RT_FAILURE(rc))
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: Failed to enter OHCI memory at %RHp: %Rrc\n", HCPhysOHCI, rc));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync return rc;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync RTR0MEMOBJ hMapObj;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync rc = RTR0MemObjMapKernel(&hMapObj, hMemObj, (void *)-1, 0 /*uAlignment*/, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (RT_SUCCESS(rc))
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync RTVPTRUNION uPtr;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync uPtr.pv = (void volatile *)RTR0MemObjAddress(hMapObj);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: mapping address %p\n", uPtr.pv));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (RT_VALID_PTR(uPtr.pv))
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync {
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: HcRevision=%#x\n", *uPtr.pu32));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /*
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * Do the access tests.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync bool fSuccess = TestOhciReads(uPtr);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (fSuccess)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync fSuccess = TestOhciWrites(uPtr);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync if (fSuccess)
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: Success!\n"));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync else
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: Failed!\n"));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync else
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync rc = VERR_INTERNAL_ERROR_2;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync /*
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync * Clean up.
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync */
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync RTR0MemObjFree(hMapObj, false);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync }
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync else
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: Failed to map OHCI memory at %RHp: %Rrc\n", HCPhysOHCI, rc));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync RTR0MemObjFree(hMemObj, false);
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync LogRel(("tstOhciRegisterAccess: returns %Rrc\n", rc));
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync return rc;
cde46304e0c614aad7fd63abacb0180e4e83f24cvboxsync}