|
|
/*** object.c - Object access functions
* * Copyright (c) 1996,1997 Microsoft Corporation * Author: Michael Tsang (MikeTs) * Created 01/27/97 * * MODIFICATION HISTORY */
#include "pch.h"
#ifdef LOCKABLE_PRAGMA
#pragma ACPI_LOCKABLE_DATA
#pragma ACPI_LOCKABLE_CODE
#endif
/***LP ReadObject - Read object
* * ENTRY * pctxt -> CTXT * pdataObj -> object * pdataResult -> result object * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL ReadObject(PCTXT pctxt, POBJDATA pdataObj, POBJDATA pdataResult) { TRACENAME("READOBJECT") NTSTATUS rc = STATUS_SUCCESS; PACCFIELDUNIT pafu;
ENTER(3, ("ReadObject(pctxt=%x,pdataObj=%x,pdataResult=%x)\n", pctxt, pdataObj, pdataResult));
pdataObj = GetBaseData(pdataObj);
switch (pdataObj->dwDataType) { case OBJTYPE_FIELDUNIT: if ((rc = PushFrame(pctxt, SIG_ACCFIELDUNIT, sizeof(ACCFIELDUNIT), AccFieldUnit, &pafu)) == STATUS_SUCCESS) { pafu->pdataObj = pdataObj; pafu->FrameHdr.dwfFrame = AFUF_READFIELDUNIT; pafu->pdata = pdataResult; } break;
case OBJTYPE_BUFFFIELD: rc = ReadField(pctxt, pdataObj, &((PBUFFFIELDOBJ)pdataObj->pbDataBuff)->FieldDesc, pdataResult); break;
default: ASSERT(pdataResult->dwDataType == OBJTYPE_UNKNOWN); CopyObjData(pdataResult, pdataObj);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & (DBGF_AMLTRACE_ON | DBGF_STEP_MODES)) { PRINTF("="); PrintObject(pdataResult); } #endif
}
EXIT(3, ("ReadObject=%x (Type=%s,Value=%x,Buff=%x)\n", rc, GetObjectTypeName(pdataResult->dwDataType), pdataResult->uipDataValue, pdataResult->pbDataBuff)); return rc; } //ReadObject
/***LP WriteObject - Write object
* * ENTRY * pctxt -> CTXT * pdataObj -> object * pdataSrc -> source data * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL WriteObject(PCTXT pctxt, POBJDATA pdataObj, POBJDATA pdataSrc) { TRACENAME("WRITEOBJECT") NTSTATUS rc = STATUS_SUCCESS; PACCFIELDUNIT pafu;
ENTER(3, ("WriteObject(pctxt=%x,pdataObj=%x,pdataSrc=%x)\n", pctxt, pdataObj, pdataSrc));
pdataObj = GetBaseData(pdataObj);
switch (pdataObj->dwDataType) { case OBJTYPE_FIELDUNIT: if ((rc = PushFrame(pctxt, SIG_ACCFIELDUNIT, sizeof(ACCFIELDUNIT), AccFieldUnit, &pafu)) == STATUS_SUCCESS) { pafu->pdataObj = pdataObj; pafu->pdata = pdataSrc; } break;
case OBJTYPE_BUFFFIELD: rc = WriteField(pctxt, pdataObj, &((PBUFFFIELDOBJ)pdataObj->pbDataBuff)->FieldDesc, pdataSrc); break;
case OBJTYPE_DEBUG: #ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON) { DumpObject(pdataSrc, NULL, 0); } #endif
rc = STATUS_SUCCESS; break;
case OBJTYPE_UNKNOWN: //
// Since the target object could be a global NameSpace object,
// allocate memory from the global heap just to be safe.
//
rc = DupObjData(gpheapGlobal, pdataObj, pdataSrc); break;
case OBJTYPE_INTDATA: rc = CopyObjBuffer((PUCHAR)&pdataObj->uipDataValue, sizeof(ULONG), pdataSrc); break;
case OBJTYPE_STRDATA: rc = CopyObjBuffer(pdataObj->pbDataBuff, pdataObj->dwDataLen - 1, pdataSrc); break;
case OBJTYPE_BUFFDATA: rc = CopyObjBuffer(pdataObj->pbDataBuff, pdataObj->dwDataLen, pdataSrc); break;
default: rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE, ("WriteObject: unexpected target object type (type=%s)", GetObjectTypeName(pdataObj->dwDataType))); }
EXIT(3, ("WriteObject=%x (ObjType=%s,DataType=%x,Value=%x,Buff=%x)\n", rc, GetObjectTypeName(pdataObj->dwDataType), pdataSrc->dwDataType, pdataSrc->uipDataValue, pdataSrc->pbDataBuff)); return rc; } //WriteObject
/***LP AccFieldUnit - Access a FieldUnit object
* * ENTRY * pctxt -> CTXT * pafu -> ACCFIELDUNIT * rc - status code * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL AccFieldUnit(PCTXT pctxt, PACCFIELDUNIT pafu, NTSTATUS rc) { TRACENAME("ACCFIELDUNIT") ULONG dwStage = (rc == STATUS_SUCCESS)? (pafu->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3; PFIELDUNITOBJ pfu; POBJDATA pdataParent, pdataBank; PBANKFIELDOBJ pbf;
ENTER(3, ("AccFieldUnit(Stage=%d,pctxt=%x,pafu=%x,rc=%x)\n", dwStage, pctxt, pafu, rc));
ASSERT(pafu->FrameHdr.dwSig == SIG_ACCFIELDUNIT);
pfu = (PFIELDUNITOBJ)pafu->pdataObj->pbDataBuff; switch (dwStage) { case 0: //
// Stage 0: Set bank if necessary.
//
pafu->FrameHdr.dwfFrame++; pdataParent = &pfu->pnsFieldParent->ObjData; if (pdataParent->dwDataType == OBJTYPE_BANKFIELD) { pbf = (PBANKFIELDOBJ)pdataParent->pbDataBuff; pdataBank = &pbf->pnsBank->ObjData; rc = PushAccFieldObj(pctxt, WriteFieldObj, pdataBank, &((PFIELDUNITOBJ)pdataBank->pbDataBuff)->FieldDesc, (PUCHAR)&pbf->dwBankValue, sizeof(ULONG)); break; }
case 1: //
// Stage 1: Acquire GlobalLock if necessary.
//
pafu->FrameHdr.dwfFrame++; if (NeedGlobalLock(pfu)) { if ((rc = AcquireGL(pctxt)) != STATUS_SUCCESS) { break; } }
case 2: //
// Stage 2: Read/Write the field.
//
pafu->FrameHdr.dwfFrame++; //
// If we come here and we need global lock, we must have got it.
//
if (pfu->FieldDesc.dwFieldFlags & FDF_NEEDLOCK) { pafu->FrameHdr.dwfFrame |= AFUF_HAVE_GLOBALLOCK; }
if (pafu->FrameHdr.dwfFrame & AFUF_READFIELDUNIT) { rc = ReadField(pctxt, pafu->pdataObj, &pfu->FieldDesc, pafu->pdata); } else { rc = WriteField(pctxt, pafu->pdataObj, &pfu->FieldDesc, pafu->pdata); }
if ((rc == AMLISTA_PENDING) || (&pafu->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd)) { break; }
case 3: //
// Stage 3: Clean up.
//
if (pafu->FrameHdr.dwfFrame & AFUF_HAVE_GLOBALLOCK) { ReleaseGL(pctxt); }
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & (DBGF_AMLTRACE_ON | DBGF_STEP_MODES)) { if (pafu->FrameHdr.dwfFrame & AFUF_READFIELDUNIT) { PRINTF("="); PrintObject(pafu->pdata); } } #endif
PopFrame(pctxt); }
EXIT(3, ("AccFieldUnit=%x\n", rc)); return rc; } //AccFieldUnit
/***LP ReadField - Read data from a field object
* * ENTRY * pctxt -> CTXT * pdataObj -> object * pfd -> field descriptor * pdataResult -> result object * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL ReadField(PCTXT pctxt, POBJDATA pdataObj, PFIELDDESC pfd, POBJDATA pdataResult) { TRACENAME("READFIELD") NTSTATUS rc = STATUS_SUCCESS;
ENTER(3, ("ReadField(pctxt=%x,pdataObj=%x,FieldDesc=%x,pdataResult=%x)\n", pctxt, pdataObj, pfd, pdataResult));
if ((pfd->dwFieldFlags & ACCTYPE_MASK) <= ACCTYPE_DWORD) { PUCHAR pb; ULONG dwcb;
switch (pdataResult->dwDataType) { case OBJTYPE_UNKNOWN: if (!(pfd->dwFieldFlags & FDF_BUFFER_TYPE) && (pfd->dwNumBits <= sizeof(ULONG)*8)) { pdataResult->dwDataType = OBJTYPE_INTDATA; pb = (PUCHAR)&pdataResult->uipDataValue; dwcb = sizeof(ULONG); } else { pdataResult->dwDataType = OBJTYPE_BUFFDATA; pdataResult->dwDataLen = (pfd->dwNumBits + 7)/8; if ((pdataResult->pbDataBuff = NEWBDOBJ(gpheapGlobal, pdataResult->dwDataLen)) == NULL) { rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM, ("ReadField: failed to allocate target buffer (size=%d)", pdataResult->dwDataLen)); pb = NULL; dwcb = 0; } else { MEMZERO(pdataResult->pbDataBuff, pdataResult->dwDataLen); pb = pdataResult->pbDataBuff; dwcb = pdataResult->dwDataLen; } } break;
case OBJTYPE_INTDATA: pb = (PUCHAR)&pdataResult->uipDataValue; dwcb = sizeof(ULONG); break;
case OBJTYPE_STRDATA: pb = pdataResult->pbDataBuff; dwcb = pdataResult->dwDataLen - 1; break;
case OBJTYPE_BUFFDATA: pb = pdataResult->pbDataBuff; dwcb = pdataResult->dwDataLen; break;
default: rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE, ("ReadField: invalid target data type (type=%s)", GetObjectTypeName(pdataResult->dwDataType))); pb = NULL; dwcb = 0; }
if (rc == STATUS_SUCCESS) rc = PushAccFieldObj(pctxt, ReadFieldObj, pdataObj, pfd, pb, dwcb); } else if (pdataObj->dwDataType == OBJTYPE_FIELDUNIT) { //
// This is an access type we don't know how to handle, so try to find
// a raw access handler to handle it.
//
rc = RawFieldAccess(pctxt, RSACCESS_READ, pdataObj, pdataResult); } else { rc = AMLI_LOGERR(AMLIERR_INVALID_ACCSIZE, ("ReadField: invalid access size for buffer field (FieldFlags=%x)", pfd->dwFieldFlags)); }
EXIT(3, ("ReadField=%x\n", rc)); return rc; } //ReadField
/***LP WriteField - Write data to a field object
* * ENTRY * pctxt -> CTXT * pdataObj -> object * pfd -> field descriptor * pdataSrc -> source data * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL WriteField(PCTXT pctxt, POBJDATA pdataObj, PFIELDDESC pfd, POBJDATA pdataSrc) { TRACENAME("WRITEFIELD") NTSTATUS rc = STATUS_SUCCESS; ULONG dwDataInc = (pfd->dwNumBits + 7)/8; PUCHAR pbBuff; ULONG dwBuffSize;
ENTER(3, ("WriteField(pctxt=%x,pdataObj=%x,FieldDesc=%x,pdataSrc=%x)\n", pctxt, pdataObj, pfd, pdataSrc));
if ((pfd->dwFieldFlags & ACCTYPE_MASK) <= ACCTYPE_DWORD) { PWRFIELDLOOP pwfl;
switch (pdataSrc->dwDataType) { case OBJTYPE_INTDATA: dwBuffSize = MIN(sizeof(ULONG), dwDataInc); pbBuff = (PUCHAR)&pdataSrc->uipDataValue; break;
case OBJTYPE_STRDATA: dwBuffSize = pdataSrc->dwDataLen - 1; pbBuff = pdataSrc->pbDataBuff; break;
case OBJTYPE_BUFFDATA: dwBuffSize = pdataSrc->dwDataLen; pbBuff = pdataSrc->pbDataBuff; break;
default: rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE, ("WriteField: invalid source data type (type=%s)\n", GetObjectTypeName(pdataSrc->dwDataType))); dwBuffSize = 0; pbBuff = NULL; }
if ((rc == STATUS_SUCCESS) && ((rc = PushFrame(pctxt, SIG_WRFIELDLOOP, sizeof(WRFIELDLOOP), WriteFieldLoop, &pwfl)) == STATUS_SUCCESS)) { pwfl->pdataObj = pdataObj; pwfl->pfd = pfd; pwfl->pbBuff = pbBuff; pwfl->dwBuffSize = dwBuffSize; pwfl->dwDataInc = dwDataInc; } } else if (pdataObj->dwDataType == OBJTYPE_FIELDUNIT) { //
// This is an access type we don't know how to handle, so try to find
// a raw access handler to handle it.
//
rc = RawFieldAccess(pctxt, RSACCESS_WRITE, pdataObj, pdataSrc); } else { rc = AMLI_LOGERR(AMLIERR_INVALID_ACCSIZE, ("WriteField: invalid access size for buffer field (FieldFlags=%x)", pfd->dwFieldFlags)); }
EXIT(3, ("WriteField=%x\n", rc)); return rc; } //WriteField
/***LP WriteFieldLoop - executing the loop for the WriteField operation
* * ENTRY * pctxt -> CTXT * pwfl -> WRFIELDLOOP * rc - status code * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL WriteFieldLoop(PCTXT pctxt, PWRFIELDLOOP pwfl, NTSTATUS rc) { TRACENAME("WRITEFIELDLOOP") ULONG dwStage = (rc == STATUS_SUCCESS)? (pwfl->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 1; ULONG dwXactionSize;
ENTER(3, ("WriteFieldLoop(Stage=%d,pctxt=%x,pwfl=%x,rc=%x)\n", dwStage, pctxt, pwfl, rc));
ASSERT(pwfl->FrameHdr.dwSig == SIG_WRFIELDLOOP);
switch (dwStage) { case 0: //
// Stage 0: Do loop.
//
if (pwfl->dwBuffSize > 0) { dwXactionSize = MIN(pwfl->dwDataInc, pwfl->dwBuffSize); rc = PushAccFieldObj(pctxt, WriteFieldObj, pwfl->pdataObj, pwfl->pfd, pwfl->pbBuff, dwXactionSize); pwfl->dwBuffSize -= dwXactionSize; pwfl->pbBuff += dwXactionSize; break; }
pwfl->FrameHdr.dwfFrame++;
case 1: //
// Stage 1: Clean up.
//
PopFrame(pctxt); }
EXIT(3, ("WriteFieldLoop=%x\n", rc)); return rc; } //WriteFieldLoop
/***LP PushAccFieldObj - Push a AccFieldObj frame on the stack
* * ENTRY * pctxt -> CTXT * pfnAcc -> access function * pdataObj -> object * pfd -> field descriptor * pb -> data buffer * dwcb - buffer size * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL PushAccFieldObj(PCTXT pctxt, PFNPARSE pfnAcc, POBJDATA pdataObj, PFIELDDESC pfd, PUCHAR pb, ULONG dwcb) { TRACENAME("PUSHACCFIELDOBJ") NTSTATUS rc = STATUS_SUCCESS; PACCFIELDOBJ pafo;
ENTER(3, ("PushAccFieldObj(pctxt=%x,pfnAcc=%x,pdataObj=%x,FieldDesc=%x,pb=%x,Size=%d)\n", pctxt, pfnAcc, pdataObj, pfd, pb, dwcb));
if ((rc = PushFrame(pctxt, SIG_ACCFIELDOBJ, sizeof(ACCFIELDOBJ), pfnAcc, &pafo)) == STATUS_SUCCESS) { pafo->pdataObj = pdataObj; pafo->pbBuff = pb; pafo->pbBuffEnd = pb + dwcb; pafo->dwAccSize = ACCSIZE(pfd->dwFieldFlags); ASSERT((pafo->dwAccSize == sizeof(UCHAR)) || (pafo->dwAccSize == sizeof(USHORT)) || (pafo->dwAccSize == sizeof(ULONG))); pafo->dwcAccesses = (pfd->dwStartBitPos + pfd->dwNumBits + pafo->dwAccSize*8 - 1)/(pafo->dwAccSize*8); pafo->dwDataMask = SHIFTLEFT(1L, pafo->dwAccSize*8) - 1; pafo->iLBits = pafo->dwAccSize*8 - pfd->dwStartBitPos; pafo->iRBits = (int)pfd->dwStartBitPos; MEMCPY(&pafo->fd, pfd, sizeof(FIELDDESC)); }
EXIT(3, ("PushAccFieldObj=%x\n", rc)); return rc; } //PushAccFieldObj
/***LP ReadFieldObj - Read data from a field object
* * ENTRY * pctxt -> CTXT * pafo -> ACCFIELDOBJ * rc - status code * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL ReadFieldObj(PCTXT pctxt, PACCFIELDOBJ pafo, NTSTATUS rc) { TRACENAME("READFIELDOBJ") ULONG dwStage = (rc == STATUS_SUCCESS)? (pafo->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3; POBJDATA pdataParent;
ENTER(3, ("ReadFieldObj(Stage=%d,pctxt=%x,pafo=%x,rc=%x)\n", dwStage, pctxt, pafo, rc));
ASSERT(pafo->FrameHdr.dwSig == SIG_ACCFIELDOBJ);
switch (dwStage) { case 0: Stage0: //
// Stage 0: Set Index if necessary.
//
if (pafo->iAccess >= (int)pafo->dwcAccesses) { //
// No access necessary, go straight to clean up.
//
pafo->FrameHdr.dwfFrame += 3; goto Stage3; } else { pafo->FrameHdr.dwfFrame++; if (pafo->pdataObj->dwDataType == OBJTYPE_FIELDUNIT) { pdataParent = &((PFIELDUNITOBJ)pafo->pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD) { PINDEXFIELDOBJ pif = (PINDEXFIELDOBJ)pdataParent->pbDataBuff;
rc = PushAccFieldObj(pctxt, WriteFieldObj, &pif->pnsIndex->ObjData, &((PFIELDUNITOBJ)pif->pnsIndex->ObjData.pbDataBuff)->FieldDesc, (PUCHAR)&pafo->fd.dwByteOffset, sizeof(ULONG)); break; } } }
case 1: //
// Stage 1: Access field data.
//
pafo->FrameHdr.dwfFrame++; rc = AccessFieldData(pctxt, pafo->pdataObj, &pafo->fd, &pafo->dwData, TRUE);
if ((rc != STATUS_SUCCESS) || (&pafo->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd)) { break; }
case 2: //
// Stage 2: Massage data into the right bit position.
//
if (pafo->iAccess > 0) { WriteSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize, SHIFTLEFT(pafo->dwData, pafo->iLBits) & pafo->dwDataMask, (SHIFTLEFT(1L, pafo->iRBits) - 1) << pafo->iLBits);
pafo->pbBuff += pafo->dwAccSize; if (pafo->pbBuff >= pafo->pbBuffEnd) { //
// We ran out of buffer, so we are done (go to clean up).
//
pafo->FrameHdr.dwfFrame++; goto Stage3; } }
pafo->dwData >>= pafo->iRBits; if ((int)pafo->fd.dwNumBits < pafo->iLBits) { pafo->dwData &= SHIFTLEFT(1L, pafo->fd.dwNumBits) - 1; }
WriteSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize, pafo->dwData, (SHIFTLEFT(1L, pafo->iLBits) - 1) >> pafo->iRBits);
pafo->fd.dwByteOffset += pafo->dwAccSize; pafo->fd.dwNumBits -= pafo->dwAccSize*8 - pafo->fd.dwStartBitPos; pafo->fd.dwStartBitPos = 0; pafo->iAccess++; if (pafo->iAccess < (int)pafo->dwcAccesses) { //
// Still more accesses to go, back to stage 0.
//
pafo->FrameHdr.dwfFrame -= 2; goto Stage0; } else { //
// No more accesses, continue to clean up.
//
pafo->FrameHdr.dwfFrame++; }
case 3: Stage3: //
// Stage 3: Clean up.
//
PopFrame(pctxt); }
EXIT(3, ("ReadFieldObj=%x\n", rc)); return rc; } //ReadFieldObj
/***LP WriteFieldObj - Write data to a field object
* * ENTRY * pctxt -> CTXT * pafo -> ACCFIELDOBJ * rc - status code * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL WriteFieldObj(PCTXT pctxt, PACCFIELDOBJ pafo, NTSTATUS rc) { TRACENAME("WRITEFIELDOBJ") ULONG dwStage = (rc == STATUS_SUCCESS)? (pafo->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3; POBJDATA pdataParent; ULONG dwData1;
ENTER(3, ("WriteFieldObj(Stage=%d,pctxt=%x,pafo=%x,rc=%x)\n", dwStage, pctxt, pafo, rc));
ASSERT(pafo->FrameHdr.dwSig == SIG_ACCFIELDOBJ);
switch (dwStage) { case 0: Stage0: //
// Stage 0: Set Index if necessary.
//
if (pafo->iAccess >= (int)pafo->dwcAccesses) { //
// No access necessary, go straight to clean up.
//
pafo->FrameHdr.dwfFrame += 3; goto Stage3; } else { pafo->FrameHdr.dwfFrame++; if (pafo->pdataObj->dwDataType == OBJTYPE_FIELDUNIT) { pdataParent = &((PFIELDUNITOBJ)pafo->pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD) { PINDEXFIELDOBJ pif = (PINDEXFIELDOBJ)pdataParent->pbDataBuff;
rc = PushAccFieldObj(pctxt, WriteFieldObj, &pif->pnsIndex->ObjData, &((PFIELDUNITOBJ)pif->pnsIndex->ObjData.pbDataBuff)->FieldDesc, (PUCHAR)&pafo->fd.dwByteOffset, sizeof(ULONG)); break; } } }
case 1: //
// Stage 1: Massage data into the right bit position and write it.
//
pafo->FrameHdr.dwfFrame++; dwData1 = ReadSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize, pafo->dwDataMask); if (pafo->iAccess > 0) { pafo->dwData = dwData1 >> pafo->iLBits; pafo->pbBuff += pafo->dwAccSize; if (pafo->pbBuff >= pafo->pbBuffEnd) { dwData1 = 0; } else { dwData1 = ReadSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize, pafo->dwDataMask); } } else { pafo->dwData = 0; }
pafo->dwData |= (dwData1 << pafo->iRBits) & pafo->dwDataMask;
rc = AccessFieldData(pctxt, pafo->pdataObj, &pafo->fd, &pafo->dwData, FALSE);
if ((rc == AMLISTA_PENDING) || (&pafo->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd)) { break; }
case 2: //
// Stage 2: Check for more iterations.
//
pafo->fd.dwByteOffset += pafo->dwAccSize; pafo->fd.dwNumBits -= pafo->dwAccSize*8 - pafo->fd.dwStartBitPos; pafo->fd.dwStartBitPos = 0; pafo->iAccess++; if (pafo->iAccess < (int)pafo->dwcAccesses) { //
// Still more accesses to go, back to stage 0.
//
pafo->FrameHdr.dwfFrame -= 2; goto Stage0; } else { pafo->FrameHdr.dwfFrame++; }
case 3: Stage3: //
// Stage 3: Clean up.
//
PopFrame(pctxt); }
EXIT(3, ("WriteFieldObj=%x\n", rc)); return rc; } //WriteFieldObj
/***LP RawFieldAccess - Find and call the RawAccess handler for the RegionSpace
* * ENTRY * pctxt -> CTXT * dwAccType - read/write * pdataObj -> field unit object * pdataResult -> result object * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL RawFieldAccess(PCTXT pctxt, ULONG dwAccType, POBJDATA pdataObj, POBJDATA pdataResult) { TRACENAME("RAWFIELDACCESS") NTSTATUS rc = STATUS_SUCCESS; POBJDATA pdataParent; POPREGIONOBJ pop; PRSACCESS prsa; PFIELDUNITOBJ pfuFieldUnit;
ENTER(3, ("RawFieldAccess(pctxt=%x,AccType=%x,pdataObj=%x,pdata=%x)\n", pctxt, dwAccType, pdataObj, pdataResult));
pdataParent = &((PFIELDUNITOBJ)pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
switch (pdataParent->dwDataType) { case OBJTYPE_FIELD: pop = (POPREGIONOBJ) ((PFIELDOBJ)pdataParent->pbDataBuff)->pnsBase->ObjData.pbDataBuff; break;
default: rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED, ("RawFieldAccess: invalid field parent type (type=%s)", pdataParent->dwDataType)); pop = NULL; }
if (rc == STATUS_SUCCESS) { if (((prsa = FindRSAccess(pop->bRegionSpace)) != NULL) && (prsa->pfnRawAccess != NULL)) { #ifdef DEBUGGER
ULONG dwOldFlags = gDebugger.dwfDebugger;
if (dwOldFlags & DBGF_AMLTRACE_ON) { gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON; } #endif
ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
if ((pfuFieldUnit = NEWFUOBJ(pctxt->pheapCurrent, sizeof (FIELDUNITOBJ))) == NULL) { rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM, ("RawFieldAccess: failed to allocate Field unit")); } else { RtlCopyMemory (pfuFieldUnit, (PFIELDUNITOBJ)pdataObj->pbDataBuff, sizeof (FIELDUNITOBJ)); pfuFieldUnit->FieldDesc.dwByteOffset += (ULONG) pop->uipOffset; rc = prsa->pfnRawAccess(dwAccType, pfuFieldUnit, pdataResult, prsa->uipRawParam, RestartCtxtCallback, &pctxt->CtxtData); if (rc == STATUS_BUFFER_TOO_SMALL) { //
// When opregion handler returns STATUS_BUFFER_TOO_SMALL, this indicates that it
// needs to have a buffer alloocated for it. The buffer size is returned in
// pdataResult->dwDataValue
//
ASSERT(pdataResult->dwDataType == OBJTYPE_INTDATA); if ((pdataResult->pbDataBuff = NEWBDOBJ(gpheapGlobal, pdataResult->dwDataValue)) == NULL) { rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM, ("Buffer: failed to allocate data buffer (size=%d)", pdataResult->dwDataValue)); } else { pdataResult->dwDataLen = pdataResult->dwDataValue; pdataResult->dwDataType = OBJTYPE_BUFFDATA; rc = prsa->pfnRawAccess(dwAccType, pfuFieldUnit, pdataResult, prsa->uipRawParam, RestartCtxtCallback, &pctxt->CtxtData); } } } #ifdef DEBUGGER
gDebugger.dwfDebugger = dwOldFlags; #endif
if (rc == STATUS_PENDING) { rc = AMLISTA_PENDING; } else if (rc != STATUS_SUCCESS) { rc = AMLI_LOGERR(AMLIERR_RS_ACCESS, ("RawFieldAccess: RegionSpace %x handler returned error %x", pop->bRegionSpace, rc)); } } else { rc = AMLI_LOGERR(AMLIERR_INVALID_REGIONSPACE, ("RawFieldAccess: no handler for RegionSpace %x", pop->bRegionSpace)); } }
EXIT(3, ("RawFieldAccess=%x\n", rc)); return rc; } //RawFieldAccess
/***LP AccessFieldData - Read/Write field object data
* * ENTRY * pctxt -> CTXT * pdataObj -> object * pfd -> field descriptor * pdwData -> to hold data read or data to be written * fRead - TRUE if read access * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL AccessFieldData(PCTXT pctxt, POBJDATA pdataObj, PFIELDDESC pfd, PULONG pdwData, BOOLEAN fRead) { TRACENAME("ACCESSFIELDDATA") NTSTATUS rc = STATUS_SUCCESS;
ENTER(3, ("AccessFieldData(pctxt=%x,pdataObj=%x,FieldDesc=%x,pdwData=%x,fRead=%x)\n", pctxt, pdataObj, pfd, pdwData, fRead));
if (pdataObj->dwDataType == OBJTYPE_BUFFFIELD) { if (fRead) { rc = ReadBuffField((PBUFFFIELDOBJ)pdataObj->pbDataBuff, pfd, pdwData); } else { rc = WriteBuffField((PBUFFFIELDOBJ)pdataObj->pbDataBuff, pfd, *pdwData); } } else //must be OBJTYPE_FIELDUNIT
{ POBJDATA pdataParent; PNSOBJ pnsBase = NULL;
pdataParent = &((PFIELDUNITOBJ)pdataObj->pbDataBuff)->pnsFieldParent->ObjData; if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD) { PINDEXFIELDOBJ pif = (PINDEXFIELDOBJ)pdataParent->pbDataBuff;
if (fRead) { rc = PushAccFieldObj(pctxt, ReadFieldObj, &pif->pnsData->ObjData, &((PFIELDUNITOBJ)pif->pnsData->ObjData.pbDataBuff)->FieldDesc, (PUCHAR)pdwData, sizeof(ULONG)); } else { ULONG dwPreserveMask, dwAccMask;
dwPreserveMask = ~((SHIFTLEFT(1L, pfd->dwNumBits) - 1) << pfd->dwStartBitPos); dwAccMask = SHIFTLEFT(1L, ACCSIZE(pfd->dwFieldFlags)*8) - 1; if (((pfd->dwFieldFlags & UPDATERULE_MASK) == UPDATERULE_PRESERVE) && ((dwPreserveMask & dwAccMask) != 0)) { rc = PushPreserveWriteObj(pctxt, &pif->pnsData->ObjData, *pdwData, dwPreserveMask); } else { rc = PushAccFieldObj(pctxt, WriteFieldObj, &pif->pnsData->ObjData, &((PFIELDUNITOBJ)pif->pnsData->ObjData.pbDataBuff)->FieldDesc, (PUCHAR)pdwData, sizeof(ULONG)); } } } else if ((rc = GetFieldUnitRegionObj( (PFIELDUNITOBJ)pdataObj->pbDataBuff, &pnsBase)) == STATUS_SUCCESS && pnsBase != NULL) { rc = AccessBaseField(pctxt, pnsBase, pfd, pdwData, fRead); } }
EXIT(3, ("AccessFieldData=%x (Data=%x)\n", rc, pdwData? *pdwData: 0)); return rc; } //AccessFieldData
/***LP PushPreserveWriteObj - Push a PreserveWrObj frame on the stack
* * ENTRY * pctxt -> CTXT * pdataObj -> object * dwData - data to be written * dwPreserveMask - preserve bit mask * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL PushPreserveWriteObj(PCTXT pctxt, POBJDATA pdataObj, ULONG dwData, ULONG dwPreserveMask) { TRACENAME("PUSHPRESERVEWRITEOBJ") NTSTATUS rc = STATUS_SUCCESS; PPRESERVEWROBJ ppwro;
ENTER(3, ("PushPreserveWriteObj(pctxt=%x,pdataObj=%x,Data=%x,PreserveMask=%x)\n", pctxt, pdataObj, dwData, dwPreserveMask));
if ((rc = PushFrame(pctxt, SIG_PRESERVEWROBJ, sizeof(PRESERVEWROBJ), PreserveWriteObj, &ppwro)) == STATUS_SUCCESS) { ppwro->pdataObj = pdataObj; ppwro->dwWriteData = dwData; ppwro->dwPreserveMask = dwPreserveMask; }
EXIT(3, ("PushPreserveWriteObj=%x\n", rc)); return rc; } //PushPreserveWriteObj
/***LP PreserveWriteObj - Preserve Write data to a field object
* * ENTRY * pctxt -> CTXT * ppwro -> PRESERVEWROBJ * rc - status code * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL PreserveWriteObj(PCTXT pctxt, PPRESERVEWROBJ ppwro, NTSTATUS rc) { TRACENAME("PRESERVEWRITEOBJ") ULONG dwStage = (rc == STATUS_SUCCESS)? (ppwro->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 2;
ENTER(3, ("PreserveWriteObj(Stage=%d,pctxt=%x,ppwro=%x,rc=%x)\n", dwStage, pctxt, ppwro, rc));
ASSERT(ppwro->FrameHdr.dwSig == SIG_PRESERVEWROBJ);
switch (dwStage) { case 0: //
// Stage 0: Read the object first.
//
ppwro->FrameHdr.dwfFrame++; rc = PushAccFieldObj(pctxt, ReadFieldObj, ppwro->pdataObj, &((PFIELDUNITOBJ)ppwro->pdataObj->pbDataBuff)->FieldDesc, (PUCHAR)&ppwro->dwReadData, sizeof(ULONG)); break;
case 1: //
// Stage 1: OR the preserve bits to the data to be written and
// write it.
//
ppwro->FrameHdr.dwfFrame++; ppwro->dwWriteData |= ppwro->dwReadData & ppwro->dwPreserveMask; rc = PushAccFieldObj(pctxt, WriteFieldObj, ppwro->pdataObj, &((PFIELDUNITOBJ)ppwro->pdataObj->pbDataBuff)->FieldDesc, (PUCHAR)&ppwro->dwWriteData, sizeof(ULONG)); break;
case 2: //
// Stage 2: Clean up.
//
PopFrame(pctxt); }
EXIT(3, ("PreserveWriteObj=%x\n", rc)); return rc; } //PreserveWriteObj
/***LP AccessBaseField - Access the base field object
* * ENTRY * pctxt -> CTXT * pnsBase -> OpRegion object * pfd -> FIELDDESC * pdwData -> result data (for read access) or data to be written * fRead - TRUE if read access * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code * * NOTE * If pdwData is NULL, it implies a read access. */
NTSTATUS LOCAL AccessBaseField(PCTXT pctxt, PNSOBJ pnsBase, PFIELDDESC pfd, PULONG pdwData, BOOLEAN fRead) { TRACENAME("ACCESSBASEFIELD") NTSTATUS rc = STATUS_SUCCESS; POPREGIONOBJ pop; ULONG_PTR uipAddr; ULONG dwSize, dwDataMask, dwAccMask; PRSACCESS prsa; BOOLEAN fPreserve;
ENTER(3, ("AccessBaseField(pctxt=%x,pnsBase=%x,pfd=%x,pdwData=%x,fRead=%x)\n", pctxt, pnsBase, pfd, pdwData, fRead));
ASSERT(pnsBase->ObjData.dwDataType == OBJTYPE_OPREGION); pop = (POPREGIONOBJ)pnsBase->ObjData.pbDataBuff; uipAddr = (ULONG_PTR)(pop->uipOffset + pfd->dwByteOffset); dwSize = ACCSIZE(pfd->dwFieldFlags); dwDataMask = (SHIFTLEFT(1L, pfd->dwNumBits) - 1) << pfd->dwStartBitPos; dwAccMask = SHIFTLEFT(1L, dwSize*8) - 1; fPreserve = (BOOLEAN)(((pfd->dwFieldFlags & UPDATERULE_MASK) == UPDATERULE_PRESERVE) && ((~dwDataMask & dwAccMask) != 0));
//
// update the result so we are left only with the relavant bits
//
*pdwData &= dwDataMask; if (!fRead && ((pfd->dwFieldFlags & UPDATERULE_MASK) == UPDATERULE_WRITEASONES)) { *pdwData |= ~dwDataMask; }
switch (pop->bRegionSpace) { case REGSPACE_MEM: if (fRead) { *pdwData = ReadSystemMem(uipAddr, dwSize, dwDataMask); } else { if (fPreserve) { *pdwData |= ReadSystemMem(uipAddr, dwSize, ~dwDataMask); }
WriteSystemMem(uipAddr, dwSize, *pdwData, dwAccMask); } break;
case REGSPACE_IO: if (fRead) { *pdwData = ReadSystemIO((ULONG)uipAddr, dwSize, dwDataMask); } else { if (fPreserve) { *pdwData |= ReadSystemIO((ULONG)uipAddr, dwSize, ~dwDataMask); }
WriteSystemIO((ULONG)uipAddr, dwSize, *pdwData); } break;
default: if (((prsa = FindRSAccess(pop->bRegionSpace)) != NULL) && (prsa->pfnCookAccess != NULL)) { if (fRead) { #ifdef DEBUGGER
ULONG dwOldFlags = gDebugger.dwfDebugger;
if (dwOldFlags & DBGF_TRACE_NONEST) { gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON; } #endif
//
// Read access.
//
ASSERT(!(pctxt->dwfCtxt & CTXTF_READY)); rc = prsa->pfnCookAccess(RSACCESS_READ, pnsBase, uipAddr, dwSize, pdwData, prsa->uipCookParam, RestartCtxtCallback, &pctxt->CtxtData); #ifdef DEBUGGER
gDebugger.dwfDebugger = dwOldFlags; #endif
if (rc == STATUS_PENDING) { rc = AMLISTA_PENDING; } else if (rc != STATUS_SUCCESS) { rc = AMLI_LOGERR(AMLIERR_RS_ACCESS, ("AccessBaseField: RegionSpace %x read handler returned error %x", pop->bRegionSpace, rc)); } } else { PWRCOOKACC pwca; //
// Write access.
//
if ((rc = PushFrame(pctxt, SIG_WRCOOKACC, sizeof(WRCOOKACC), WriteCookAccess, &pwca)) == STATUS_SUCCESS) { pwca->pnsBase = pnsBase; pwca->prsa = prsa; pwca->dwAddr = (ULONG)uipAddr; pwca->dwSize = dwSize; pwca->dwData = *pdwData; pwca->dwDataMask = dwDataMask; pwca->fPreserve = fPreserve; } } } else { rc = AMLI_LOGERR(AMLIERR_INVALID_REGIONSPACE, ("AccessBaseField: no handler for RegionSpace %x", pop->bRegionSpace)); } }
EXIT(3, ("AccessBaseField=%x (Value=%x,Addr=%x,Size=%d,DataMask=%x,AccMask=%x)\n", rc, *pdwData, uipAddr, dwSize, dwDataMask, dwAccMask)); return rc; } //AccessBaseField
/***LP WriteCookAccess - do a region space write cook access
* * ENTRY * pctxt -> CTXT * pwca -> WRCOOKACC * rc - status code * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL WriteCookAccess(PCTXT pctxt, PWRCOOKACC pwca, NTSTATUS rc) { TRACENAME("WRCOOKACCESS") ULONG dwStage = (rc == STATUS_SUCCESS)? (pwca->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3; KIRQL oldIrql; LONG busy; POPREGIONOBJ pop = (POPREGIONOBJ)pwca->pnsBase->ObjData.pbDataBuff;
ENTER(3, ("WriteCookAccess(Stage=%d,pctxt=%x,pwca=%x,rc=%x)\n", dwStage, pctxt, pwca, rc));
ASSERT(pwca->FrameHdr.dwSig == SIG_WRCOOKACC);
switch (dwStage) { case 0: //
// Stage 0: if PRESERVE, do read first.
//
if (pwca->fPreserve) { #ifdef DEBUGGER
ULONG dwOldFlags = gDebugger.dwfDebugger;
if (dwOldFlags & DBGF_TRACE_NONEST) { gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON; } #endif
KeAcquireSpinLock(&pop->listLock, &oldIrql); if (busy = InterlockedExchange(&pop->RegionBusy, TRUE)) {
//
// Somebody is currently using this operation region.
// Queue this context so that it can be re-started later.
//
QueueContext(pctxt, 0xffff, &pop->plistWaiters);
} KeReleaseSpinLock(&pop->listLock, oldIrql);
if (busy) { rc = AMLISTA_PENDING; break; }
pwca->FrameHdr.dwfFrame++; ASSERT(!(pctxt->dwfCtxt & CTXTF_READY)); rc = pwca->prsa->pfnCookAccess(RSACCESS_READ, pwca->pnsBase, (ULONG_PTR)pwca->dwAddr, pwca->dwSize, &pwca->dwDataTmp, pwca->prsa->uipCookParam, RestartCtxtCallback, &pctxt->CtxtData); #ifdef DEBUGGER
gDebugger.dwfDebugger = dwOldFlags; #endif
if (rc == STATUS_PENDING) { rc = AMLISTA_PENDING; } else if (rc != STATUS_SUCCESS) { rc = AMLI_LOGERR(AMLIERR_RS_ACCESS, ("WriteCookAccess: RegionSpace %x read handler returned error %x", pop->bRegionSpace, rc)); }
if (rc != STATUS_SUCCESS) { break; } } else { //
// No preserve, we can skip the ORing.
//
pwca->FrameHdr.dwfFrame += 2; goto Stage2; }
case 1: //
// Stage 1: OR the preserved bits.
//
pwca->dwData |= pwca->dwDataTmp & ~pwca->dwDataMask; pwca->FrameHdr.dwfFrame++;
case 2: Stage2: //
// Stage 2: Write the data.
//
#ifdef DEBUGGER
{ ULONG dwOldFlags = gDebugger.dwfDebugger;
if (dwOldFlags & DBGF_TRACE_NONEST) { gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON; } #endif
pwca->FrameHdr.dwfFrame++; ASSERT(!(pctxt->dwfCtxt & CTXTF_READY)); rc = pwca->prsa->pfnCookAccess(RSACCESS_WRITE, pwca->pnsBase, (ULONG_PTR)pwca->dwAddr, pwca->dwSize, &pwca->dwData, pwca->prsa->uipCookParam, RestartCtxtCallback, &pctxt->CtxtData); #ifdef DEBUGGER
gDebugger.dwfDebugger = dwOldFlags; } #endif
if (rc == STATUS_PENDING) { rc = AMLISTA_PENDING; } else if (rc != STATUS_SUCCESS) { rc = AMLI_LOGERR(AMLIERR_RS_ACCESS, ("WriteCookAccess: RegionSpace %x read handler returned error %x", pop->bRegionSpace, rc)); }
if (rc != STATUS_SUCCESS) { break; }
case 3: if (pwca->fPreserve) { KeAcquireSpinLock(&pop->listLock, &oldIrql);
//
// Restart anybody who blocked while we were in here.
//
DequeueAndReadyContext(&pop->plistWaiters);
//
// Release the lock on this op-region.
//
InterlockedExchange(&pop->RegionBusy, FALSE);
KeReleaseSpinLock(&pop->listLock, oldIrql); } //
// Stage 3: Clean up.
//
PopFrame(pctxt); }
EXIT(3, ("WriteCookAccess=%x\n", rc)); return rc; } //WriteCookAccess
/***LP ReadBuffField - Read data from a buffer field
* * ENTRY * pbf -> buffer field object * pfd -> field descriptor * pdwData -> to hold result data * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL ReadBuffField(PBUFFFIELDOBJ pbf, PFIELDDESC pfd, PULONG pdwData) { TRACENAME("READBUFFFIELD") NTSTATUS rc = STATUS_SUCCESS; ULONG dwAccSize = ACCSIZE(pfd->dwFieldFlags);
ENTER(3, ("ReadBuffField(pbf=%x,pfd=%x,pdwData=%x)\n", pbf, pfd, pdwData));
if (pfd->dwByteOffset + dwAccSize <= pbf->dwBuffLen) { ULONG dwMask = (SHIFTLEFT(1L, pfd->dwNumBits) - 1) << pfd->dwStartBitPos;
*pdwData = ReadSystemMem((ULONG_PTR)(pbf->pbDataBuff + pfd->dwByteOffset), dwAccSize, dwMask); } else { rc = AMLI_LOGERR(AMLIERR_INDEX_TOO_BIG, ("ReadBuffField: offset exceeding buffer size (Offset=%x,BuffSize=%x,AccSize)", pfd->dwByteOffset, pbf->dwBuffLen, dwAccSize)); }
EXIT(3, ("ReadBuffField=%x (Data=%x)\n", rc, *pdwData)); return rc; } //ReadBuffField
/***LP WriteBuffField - Write data to a buffer field
* * ENTRY * pbf -> buffer field object * pfd -> field descriptor * dwData - data * * EXIT-SUCCESS * returns STATUS_SUCCESS * EXIT-FAILURE * returns AMLIERR_ code */
NTSTATUS LOCAL WriteBuffField(PBUFFFIELDOBJ pbf, PFIELDDESC pfd, ULONG dwData) { TRACENAME("WRITEBUFFFIELD") NTSTATUS rc = STATUS_SUCCESS; ULONG dwAccSize = ACCSIZE(pfd->dwFieldFlags);
ENTER(3, ("WriteBuffField(pbf=%x,pfd=%x,dwData=%x)\n", pbf, pfd, dwData));
if (pfd->dwByteOffset + dwAccSize <= pbf->dwBuffLen) { ULONG dwMask = (SHIFTLEFT(1L, pfd->dwNumBits) - 1) << pfd->dwStartBitPos;
WriteSystemMem((ULONG_PTR)(pbf->pbDataBuff + pfd->dwByteOffset), dwAccSize, dwData & dwMask, dwMask); } else { rc = AMLI_LOGERR(AMLIERR_INDEX_TOO_BIG, ("WriteBuffField: offset exceeding buffer size (Offset=%x,BuffSize=%x,AccSize=%x)", pfd->dwByteOffset, pbf->dwBuffLen, dwAccSize)); }
EXIT(3, ("WriteBuffField=%x\n", rc)); return rc; } //WriteBuffField
/***LP ReadSystemMem - Read system memory
* * ENTRY * uipAddr - memory address * dwSize - size to read * dwMask - data mask * * EXIT * return memory content */
ULONG LOCAL ReadSystemMem(ULONG_PTR uipAddr, ULONG dwSize, ULONG dwMask) { TRACENAME("READSYSTEMMEM") ULONG dwData = 0; ULONG dwCount; ENTER(3, ("ReadSystemMem(Addr=%x,Size=%d,Mask=%x)\n", uipAddr, dwSize, dwMask));
ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) || (dwSize == sizeof(ULONG)));
#if defined(_IA64_)
dwCount = dwSize/sizeof(UCHAR);
ASSERT(dwCount <= (sizeof(ULONG)/sizeof(UCHAR)));
//
// check for misalignment
//
if (uipAddr % dwCount) { //
// unaligned, do the operation byte-wise
//
MEMCPY(&dwData, (PVOID)uipAddr, dwSize);
} else { //
// aligned, just do the read atomically
//
switch (dwSize) { case sizeof(UCHAR): dwData = (ULONG)READ_REGISTER_UCHAR((PUCHAR)uipAddr); break; case sizeof(USHORT): dwData = (ULONG)READ_REGISTER_USHORT((PUSHORT)uipAddr); break; case sizeof(ULONG): dwData = READ_REGISTER_ULONG((PULONG)uipAddr); break; } } #else
MEMCPY(&dwData, (PVOID)uipAddr, dwSize);
#endif
dwData &= dwMask;
EXIT(3, ("ReadSystemMem=%x\n", dwData)); return dwData; } //ReadSystemMem
/***LP WriteSystemMem - Write system memory
* * ENTRY * uipAddr - memory address * dwSize - size to write * dwData - data to write * dwMask - data mask * * EXIT * return memory content */
VOID LOCAL WriteSystemMem(ULONG_PTR uipAddr, ULONG dwSize, ULONG dwData, ULONG dwMask) { TRACENAME("WRITESYSTEMMEM") ULONG dwTmpData = 0; ULONG dwCount; ULONG SizeToMask[5] = { 0x0, 0xff, 0xffff, 0, 0xffffffff }; BOOLEAN SkipReadOperation = FALSE;
if (dwMask == SizeToMask[dwSize]) { SkipReadOperation = TRUE; } ENTER(3, ("WriteSystemMem(Addr=%x,Size=%d,Data=%x,Mask=%x)\n", uipAddr, dwSize, dwData, dwMask));
ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) || (dwSize == sizeof(ULONG)));
#if defined(_IA64_)
dwCount = dwSize/sizeof(UCHAR);
ASSERT(dwCount <= (sizeof(ULONG)/sizeof(UCHAR)));
//
// check for misalignment
//
if (uipAddr % dwCount) { //
// unaligned, do the operation byte-wise
//
if (!SkipReadOperation) { MEMCPY(&dwTmpData, (PVOID)uipAddr, dwSize); } dwTmpData &= ~dwMask; dwTmpData |= dwData; MEMCPY((PVOID)uipAddr, &dwTmpData, dwSize); } else { //
// aligned access. just get the data atomically.
//
switch (dwSize) { case sizeof(UCHAR): if (!SkipReadOperation) { dwTmpData = READ_REGISTER_UCHAR((PUCHAR)uipAddr); } dwTmpData &= ~dwMask; dwTmpData |= dwData; WRITE_REGISTER_UCHAR((PUCHAR)uipAddr, (UCHAR)dwTmpData); break; case sizeof(USHORT): if (!SkipReadOperation) { dwTmpData = READ_REGISTER_USHORT((PUCHAR)uipAddr); } dwTmpData &= ~dwMask; dwTmpData |= dwData; WRITE_REGISTER_USHORT((PUSHORT)uipAddr, (USHORT)dwTmpData); break; case sizeof(ULONG): if (!SkipReadOperation) { dwTmpData = READ_REGISTER_ULONG((PUCHAR)uipAddr); } dwTmpData &= ~dwMask; dwTmpData |= dwData; WRITE_REGISTER_ULONG((PULONG)uipAddr, dwTmpData); break; } } #else
if (!SkipReadOperation) { MEMCPY(&dwTmpData, (PVOID)uipAddr, dwSize); } dwTmpData &= ~dwMask; dwTmpData |= dwData; MEMCPY((PVOID)uipAddr, &dwTmpData, dwSize);
#endif
EXIT(3, ("WriteSystemMem!\n")); } //WriteSystemMem
/***LP ReadSystemIO - Read system IO
* * ENTRY * dwAddr - memory address * dwSize - size to read * dwMask - data mask * * EXIT * return memory content */
ULONG LOCAL ReadSystemIO(ULONG dwAddr, ULONG dwSize, ULONG dwMask) { TRACENAME("READSYSTEMIO") ULONG dwData = 0;
ENTER(3, ("ReadSystemIO(Addr=%x,Size=%d,Mask=%x)\n", dwAddr, dwSize, dwMask));
ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) || (dwSize == sizeof(ULONG)));
if(CheckSystemIOAddressValidity(TRUE, dwAddr, dwSize, &dwData)) {
//
// HACKHACK: We are adding this here because Dell Latitude laptops with Older
// BIOS (A07 and older) hang in SMI because there is a non zero value\ // in CH. We now clear CX to work around their bug.
//
#ifdef _X86_
__asm { xor cx,cx } #endif //_X86_
switch (dwSize) { case sizeof(UCHAR): dwData = (ULONG)READ_PORT_UCHAR((PUCHAR)UlongToPtr(dwAddr)); break;
case sizeof(USHORT): dwData = (ULONG)READ_PORT_USHORT((PUSHORT)UlongToPtr(dwAddr)); break;
case sizeof(ULONG): dwData = READ_PORT_ULONG((PULONG)UlongToPtr(dwAddr)); break; } } dwData &= dwMask;
EXIT(3, ("ReadSystemIO=%x\n", dwData)); return dwData; } //ReadSystemIO
/***LP WriteSystemIO - Write system IO
* * ENTRY * dwAddr - memory address * dwSize - size to write * dwData - data to write * * EXIT * return memory content */
VOID LOCAL WriteSystemIO(ULONG dwAddr, ULONG dwSize, ULONG dwData) { TRACENAME("WRITESYSTEMIO") ENTER(3, ("WriteSystemIO(Addr=%x,Size=%d,Data=%x)\n", dwAddr, dwSize, dwData));
ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) || (dwSize == sizeof(ULONG)));
if(CheckSystemIOAddressValidity(FALSE, dwAddr, dwSize, &dwData)) { //
// HACKHACK: We are adding this here because Dell Latitude laptops with Older
// BIOS (A07 and older) hang in SMI because there is a non zero value\ // in CH. We now clear CX to work around their bug.
//
#ifdef _X86_
__asm { xor cx,cx } #endif //_X86_
switch (dwSize) { case sizeof(UCHAR): WRITE_PORT_UCHAR((PUCHAR)UlongToPtr(dwAddr), (UCHAR)dwData); break;
case sizeof(USHORT): WRITE_PORT_USHORT((PUSHORT)UlongToPtr(dwAddr), (USHORT)dwData); break;
case sizeof(ULONG): WRITE_PORT_ULONG((PULONG)UlongToPtr(dwAddr), dwData); break; } } EXIT(3, ("WriteSystemIO!\n")); } //WriteSystemIO
#ifdef DEBUGGER
/***LP DumpObject - Dump object info.
* * ENTRY * pdata -> data * pszName -> object name * iLevel - indent level * * EXIT * None * * NOTE * If iLevel is negative, no indentation and newline are printed. */
VOID LOCAL DumpObject(POBJDATA pdata, PSZ pszName, int iLevel) { TRACENAME("DUMPOBJECT") BOOLEAN fPrintNewLine; int i; char szName1[sizeof(NAMESEG) + 1], szName2[sizeof(NAMESEG) + 1];
ENTER(3, ("DumpObject(pdata=%x,Name=%s,Level=%d)\n", pdata, pszName, iLevel));
fPrintNewLine = (BOOLEAN)(iLevel >= 0);
for (i = 0; i < iLevel; ++i) { PRINTF("| "); }
if (pszName == NULL) { pszName = ""; }
switch (pdata->dwDataType) { case OBJTYPE_UNKNOWN: PRINTF("Unknown(%s)", pszName); break;
case OBJTYPE_INTDATA: PRINTF("Integer(%s:Value=0x%08x[%d])", pszName, pdata->uipDataValue, pdata->uipDataValue); break;
case OBJTYPE_STRDATA: PRINTF("String(%s:Str=\"%s\")", pszName, pdata->pbDataBuff); break;
case OBJTYPE_BUFFDATA: PRINTF("Buffer(%s:Ptr=%x,Len=%d)", pszName, pdata->pbDataBuff, pdata->dwDataLen); PrintBuffData(pdata->pbDataBuff, pdata->dwDataLen); break;
case OBJTYPE_PKGDATA: PRINTF("Package(%s:NumElements=%d){", pszName, ((PPACKAGEOBJ)pdata->pbDataBuff)->dwcElements);
if (fPrintNewLine) { PRINTF("\n"); }
for (i = 0; i < (int)((PPACKAGEOBJ)pdata->pbDataBuff)->dwcElements; ++i) { DumpObject(&((PPACKAGEOBJ)pdata->pbDataBuff)->adata[i], NULL, fPrintNewLine? iLevel + 1: -1);
if (!fPrintNewLine && (i < (int)((PPACKAGEOBJ)pdata->pbDataBuff)->dwcElements)) { PRINTF(","); } }
for (i = 0; i < iLevel; ++i) { PRINTF("| "); }
PRINTF("}"); break;
case OBJTYPE_FIELDUNIT: PRINTF("FieldUnit(%s:FieldParent=%p,ByteOffset=0x%x,StartBit=0x%x,NumBits=%d,FieldFlags=0x%x)", pszName, ((PFIELDUNITOBJ)pdata->pbDataBuff)->pnsFieldParent, ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwByteOffset, ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwStartBitPos, ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwNumBits, ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwFieldFlags); break;
case OBJTYPE_DEVICE: PRINTF("Device(%s)", pszName); break;
case OBJTYPE_EVENT: PRINTF("Event(%s:pKEvent=%x)", pszName, pdata->pbDataBuff); break;
case OBJTYPE_METHOD: PRINTF("Method(%s:Flags=0x%x,CodeBuff=%p,Len=%d)", pszName, ((PMETHODOBJ)pdata->pbDataBuff)->bMethodFlags, ((PMETHODOBJ)pdata->pbDataBuff)->abCodeBuff, pdata->dwDataLen - FIELD_OFFSET(METHODOBJ, abCodeBuff)); break;
case OBJTYPE_MUTEX: PRINTF("Mutex(%s:pKMutex=%x)", pszName, pdata->pbDataBuff); break;
case OBJTYPE_OPREGION: PRINTF("OpRegion(%s:RegionSpace=%s,Offset=0x%x,Len=%d)", pszName, GetRegionSpaceName(((POPREGIONOBJ)pdata->pbDataBuff)->bRegionSpace), ((POPREGIONOBJ)pdata->pbDataBuff)->uipOffset, ((POPREGIONOBJ)pdata->pbDataBuff)->dwLen); break;
case OBJTYPE_POWERRES: PRINTF("PowerResource(%s:SystemLevel=0x%x,ResOrder=%d)", pszName, ((PPOWERRESOBJ)pdata->pbDataBuff)->bSystemLevel, ((PPOWERRESOBJ)pdata->pbDataBuff)->bResOrder); break;
case OBJTYPE_PROCESSOR: PRINTF("Processor(%s:ApicID=0x%x,PBlk=0x%x,PBlkLen=%d)", pszName, ((PPROCESSOROBJ)pdata->pbDataBuff)->bApicID, ((PPROCESSOROBJ)pdata->pbDataBuff)->dwPBlk, ((PPROCESSOROBJ)pdata->pbDataBuff)->dwPBlkLen); break;
case OBJTYPE_THERMALZONE: PRINTF("ThermalZone(%s)", pszName); break;
case OBJTYPE_BUFFFIELD: PRINTF("BufferField(%s:Ptr=%x,Len=%d,ByteOffset=0x%x,StartBit=0x%x,NumBits=%d,FieldFlags=0x%x)", pszName, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->pbDataBuff, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->dwBuffLen, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwByteOffset, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwStartBitPos, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwNumBits, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwFieldFlags); break;
case OBJTYPE_DDBHANDLE: PRINTF("DDBHandle(%s:Handle=%x)", pszName, pdata->pbDataBuff); break;
case OBJTYPE_OBJALIAS: PRINTF("ObjectAlias(%s:Alias=%s,Type=%s)", pszName, GetObjectPath(pdata->pnsAlias), GetObjectTypeName(pdata->pnsAlias->ObjData.dwDataType)); break;
case OBJTYPE_DATAALIAS: PRINTF("DataAlias(%s:Link=%x)", pszName, pdata->pdataAlias); if (fPrintNewLine) { DumpObject(pdata->pdataAlias, NULL, iLevel + 1); fPrintNewLine = FALSE; } break;
case OBJTYPE_BANKFIELD: STRCPYN(szName1, (PSZ)(&((PBANKFIELDOBJ)pdata->pbDataBuff)->pnsBase->dwNameSeg), sizeof(NAMESEG)); STRCPYN(szName2, (PSZ)(&((PBANKFIELDOBJ)pdata->pbDataBuff)->pnsBank->dwNameSeg), sizeof(NAMESEG)); PRINTF("BankField(%s:Base=%s,BankName=%s,BankValue=0x%x)", pszName, szName1, szName2, ((PBANKFIELDOBJ)pdata->pbDataBuff)->dwBankValue); break;
case OBJTYPE_FIELD: STRCPYN(szName1, (PSZ)(&((PFIELDOBJ)pdata->pbDataBuff)->pnsBase->dwNameSeg), sizeof(NAMESEG)); PRINTF("Field(%s:Base=%s)", pszName, szName1); break;
case OBJTYPE_INDEXFIELD: STRCPYN(szName1, (PSZ)(&((PINDEXFIELDOBJ)pdata->pbDataBuff)->pnsIndex->dwNameSeg), sizeof(NAMESEG)); STRCPYN(szName2, (PSZ)(&((PINDEXFIELDOBJ)pdata->pbDataBuff)->pnsData->dwNameSeg), sizeof(NAMESEG)); PRINTF("IndexField(%s:IndexName=%s,DataName=%s)", pszName, szName1, szName2); break;
default: AMLI_ERROR(("DumpObject: unexpected data object type (type=%x)", pdata->dwDataType)); }
if (fPrintNewLine) { PRINTF("\n"); }
EXIT(3, ("DumpObject!\n")); } //DumpObject
#endif
/***LP NeedGlobalLock - check if global lock is required
* * ENTRY * pfu - FIELDUNITOBJ * * EXIT-SUCCESS * returns TRUE * EXIT-FAILURE * returns FALSE */
BOOLEAN LOCAL NeedGlobalLock(PFIELDUNITOBJ pfu) { TRACENAME("NEEDGLOBALLOCK") BOOLEAN rc = FALSE;
ENTER(3, ("NeedGlobalLock(pfu=%x)\n", pfu));
if ((pfu->FieldDesc.dwFieldFlags & FDF_NEEDLOCK) || (pfu->FieldDesc.dwFieldFlags & LOCKRULE_LOCK)) { rc = TRUE; } else { POBJDATA pdataParent = &pfu->pnsFieldParent->ObjData; PFIELDUNITOBJ pfuParent;
if (pdataParent->dwDataType == OBJTYPE_BANKFIELD) { pfuParent = (PFIELDUNITOBJ) ((PBANKFIELDOBJ)pdataParent->pbDataBuff)->pnsBank->ObjData.pbDataBuff; if (pfuParent->FieldDesc.dwFieldFlags & LOCKRULE_LOCK) { rc = TRUE; } } else if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD) { pfuParent = (PFIELDUNITOBJ) ((PINDEXFIELDOBJ)pdataParent->pbDataBuff)->pnsIndex->ObjData.pbDataBuff; if (pfuParent->FieldDesc.dwFieldFlags & LOCKRULE_LOCK) { rc = TRUE; } else { pfuParent = (PFIELDUNITOBJ) ((PINDEXFIELDOBJ)pdataParent->pbDataBuff)->pnsData->ObjData.pbDataBuff; if (pfuParent->FieldDesc.dwFieldFlags & LOCKRULE_LOCK) { rc = TRUE; } } } }
if (rc == TRUE) { pfu->FieldDesc.dwFieldFlags |= FDF_NEEDLOCK; }
EXIT(3, ("NeedGlobalLock=%x\n", rc)); return rc; } //NeedGlobalLock
/***LP CheckSystemIOAddressValidity - Check if the address is a legal IO address
* * ENTRY * fRead - TRUE iff access is a read. FALSE on write * dwAddr - memory address * ULONG dwSize - Size of data * PULONG pdwData - Pointer to the data buffer. * * EXIT * return TRUE on Valid address */
BOOLEAN LOCAL CheckSystemIOAddressValidity( BOOLEAN fRead, ULONG dwAddr, ULONG dwSize, PULONG pdwData ) { TRACENAME("CHECKSYSTEMIOADDRESSVALIDITY") ULONG i = 0; BOOLEAN bRet = TRUE; ENTER(3, ("CheckSystemIOAddressValidity(fRead=%s, dwAddr=%x, dwSize=%x, pdwData=%x)\n", (fRead?"TRUE":"FALSE"),dwAddr, dwSize, pdwData));
//
// check if list exists on this platform.
//
if(gpBadIOAddressList) { //
// Walk the list till we hit the end.
//
for(i=0; gpBadIOAddressList[i].BadAddrSize != 0 ; i++) { //
// Check if the incoming address is in the range
//
if((dwAddr >= (gpBadIOAddressList[i].BadAddrBegin)) && (dwAddr < ((gpBadIOAddressList[i].BadAddrBegin) + (gpBadIOAddressList[i].BadAddrSize)))) { //
// Check if we need to ignore this address for legacy reasons.
//
if(gpBadIOAddressList[i].OSVersionTrigger <= gdwHighestOSVerQueried) { bRet = FALSE; PRINTF("CheckSystemIOAddressValidity: failing illegal IO address (0x%x).\n", dwAddr); } else { PRINTF("CheckSystemIOAddressValidity: Passing for compatibility reasons on illegal IO address (0x%x).\n", dwAddr);
if(gpBadIOAddressList[i].IOHandler) { //
// Since we are handeling this here we can return FALSE. This way the
// calling function will not process this request.
//
bRet = FALSE;
//
// Call HAL and let it handle this IO request
//
(gpBadIOAddressList[i].IOHandler)(fRead, dwAddr, dwSize, pdwData);
PRINTF("CheckSystemIOAddressValidity: HAL IO handler called to %s address (0x%x). %s 0x%8lx\n", fRead ? "read" : "write", dwAddr, fRead ? "Read" : "Wrote", *pdwData ); } }
//
// Log the illegal access to the event log.
//
if (KeGetCurrentIrql() < DISPATCH_LEVEL) { LogInErrorLog(fRead, dwAddr, i ); } else { PIO_WORKITEM Log_WorkItem = NULL; PDEVICE_OBJECT pACPIDeviceObject = ACPIGetRootDeviceObject();
if(pACPIDeviceObject) { Log_WorkItem = IoAllocateWorkItem(pACPIDeviceObject);
if(Log_WorkItem) { PAMLI_LOG_WORKITEM_CONTEXT pWorkItemContext = NULL;
pWorkItemContext = (PAMLI_LOG_WORKITEM_CONTEXT) ExAllocatePoolWithTag(NonPagedPool, sizeof(AMLI_LOG_WORKITEM_CONTEXT), PRIV_TAG ); if(pWorkItemContext) { pWorkItemContext->fRead = fRead; pWorkItemContext->Address = dwAddr; pWorkItemContext->Index = i; pWorkItemContext->pIOWorkItem = Log_WorkItem; IoQueueWorkItem( Log_WorkItem, DelayedLogInErrorLog, DelayedWorkQueue, (VOID*)pWorkItemContext ); } else { //
// not enough free pool exists to satisfy the request.
//
PRINTF("CheckSystemIOAddressValidity: Failed to allocate contxt block from pool to spin off a logging work item.\n"); IoFreeWorkItem(Log_WorkItem); } } else { //
// insufficient resources
//
PRINTF("CheckSystemIOAddressValidity: Failed to allocate a workitem to spin off delayed logging.\n");
} } else { //
// Failed to get ACPI root DeviceObject
//
PRINTF("CheckSystemIOAddressValidity: Failed to get ACPI root DeviceObject.\n"); } } break; } } }
EXIT(3, ("CheckSystemIOAddressValidity!\n")); return bRet; }
/***LP DelayedLogInErrorLog - Call LogInErrorLog
* * ENTRY * PDEVICE_OBJECT DeviceObject - Device Object. * PVOID Context - Context pointer with data to call LogInErrorLog with. * * EXIT * VOID */ VOID DelayedLogInErrorLog( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context ) { LogInErrorLog(((PAMLI_LOG_WORKITEM_CONTEXT)Context)->fRead, ((PAMLI_LOG_WORKITEM_CONTEXT)Context)->Address, ((PAMLI_LOG_WORKITEM_CONTEXT)Context)->Index );
IoFreeWorkItem((PIO_WORKITEM)((PAMLI_LOG_WORKITEM_CONTEXT)Context)->pIOWorkItem); ExFreePool(Context); }
/***LP LogInErrorLog - Log illegal IO access to event log
* * ENTRY * fRead - TRUE iff access is a read. FALSE on write * dwAddr - Memory address * ArrayIndex - Index into BadIOAddressList array. * * EXIT * None. */ VOID LOCAL LogInErrorLog(BOOLEAN fRead, ULONG dwAddr, ULONG ArrayIndex) { TRACENAME("LOGERROR") PWCHAR illegalIOPortAddress[3]; WCHAR AMLIName[6]; WCHAR addressBuffer[13]; WCHAR addressRangeBuffer[16];
ENTER(3, ("LogInErrorLog(fRead=%s, Addr=%x, ArrayIndex=%x)\n", (fRead?"TRUE":"FALSE"),dwAddr, ArrayIndex));
//
// Check to see if we need to log this address.
//
if(gpBadIOErrorLogDoneList) { //
// Check to see if we need to log this address.
//
if (!(gpBadIOErrorLogDoneList[ArrayIndex] & (fRead?READ_ERROR_NOTED:WRITE_ERROR_NOTED))) { gpBadIOErrorLogDoneList[ArrayIndex] |= (fRead?READ_ERROR_NOTED:WRITE_ERROR_NOTED);
//
// Turn the address into a string
//
swprintf( AMLIName, L"AMLI"); swprintf( addressBuffer, L"0x%x", dwAddr ); swprintf( addressRangeBuffer, L"0x%x - 0x%x", gpBadIOAddressList[ArrayIndex].BadAddrBegin, (gpBadIOAddressList[ArrayIndex].BadAddrBegin + (gpBadIOAddressList[ArrayIndex].BadAddrSize - 1))); //
// Build the list of arguments to pass to the function that will write the
// error log to the registry
//
illegalIOPortAddress[0] = AMLIName; illegalIOPortAddress[1] = addressBuffer; illegalIOPortAddress[2] = addressRangeBuffer;
//
// Log error to event log
//
ACPIWriteEventLogEntry((fRead ? ACPI_ERR_AMLI_ILLEGAL_IO_READ_FATAL : ACPI_ERR_AMLI_ILLEGAL_IO_WRITE_FATAL), illegalIOPortAddress, 3, NULL, 0);
} } EXIT(3, ("LogInErrorLog!\n"));
return; }
/***LP InitIllegalIOAddressListFromHAL - Initialize the Illegal IO
* address List from the HAL. * * ENTRY * None. * * EXIT * None. */ VOID LOCAL InitIllegalIOAddressListFromHAL(VOID) { TRACENAME("InitIllegalIOAddressListFromHAL") ULONG Length = 0; NTSTATUS status;
ENTER(3, ("InitIllegalIOAddressListFromHAL\n")); if(!gpBadIOAddressList) { //
// Query HAL to get the amount of memory to allocate
//
status = HalQuerySystemInformation ( HalQueryAMLIIllegalIOPortAddresses, 0, NULL, &Length );
if(status == STATUS_INFO_LENGTH_MISMATCH) { if(Length) { //
// Allocate memory.
//
if ((gpBadIOAddressList = (PHAL_AMLI_BAD_IO_ADDRESS_LIST) MALLOC(Length, PRIV_TAG)) == NULL) { AMLI_LOGERR(AMLIERR_OUT_OF_MEM, ("InitIllegalIOAddressListFromHAL: failed to allocate Bad IO address list.")); } else { //
// Get bad IO address list from HAL.
//
status = HalQuerySystemInformation( HalQueryAMLIIllegalIOPortAddresses, Length, gpBadIOAddressList, &Length ); //
// Cleanup on failure.
//
if(status != STATUS_SUCCESS) { PRINTF("InitIllegalIOAddressListFromHAL: HalQuerySystemInformation failed to get list from HAL. Returned(%x).\n", status); FreellegalIOAddressList(); } // Allocate the errorlogdone list. this helps us track if we have logged
// a certain address.
//
else { //
// Calculate array length
//
ULONG ArrayLength = (Length / sizeof(HAL_AMLI_BAD_IO_ADDRESS_LIST)) - 1;
if(ArrayLength >= 1) { if ((gpBadIOErrorLogDoneList = (PULONG) MALLOC((ArrayLength * sizeof(ULONG)), PRIV_TAG)) == NULL) { AMLI_LOGERR(AMLIERR_OUT_OF_MEM, ("InitIllegalIOAddressListFromHAL: failed to allocate ErrorLogDone list.")); } else { RtlZeroMemory(gpBadIOErrorLogDoneList, (ArrayLength * sizeof(ULONG)));
} } } }
} else { PRINTF("InitIllegalIOAddressListFromHAL: HalQuerySystemInformation (HalQueryIllegalIOPortAddresses) returned 0 Length.\n"); } } else if(status == STATUS_INVALID_LEVEL) { PRINTF("InitIllegalIOAddressListFromHAL: HalQuerySystemInformation does not support HalQueryIllegalIOPortAddresses returned (STATUS_INVALID_LEVEL).\n"); } else { PRINTF("InitIllegalIOAddressListFromHAL: failed. Returned(0x%08lx).\n", status); } }
EXIT(3, ("InitIllegalIOAddressListFromHAL!\n")); return; }
/***LP FreellegalIOAddressList - Free the Illegal IO
* address List. * * ENTRY * None. * * EXIT * None. */ VOID LOCAL FreellegalIOAddressList(VOID) { TRACENAME("FreellegalIOAddressList") ENTER(3, ("FreellegalIOAddressList\n")); if(gpBadIOAddressList) { MFREE(gpBadIOAddressList); gpBadIOAddressList = NULL; }
if(gpBadIOErrorLogDoneList) { MFREE(gpBadIOErrorLogDoneList); gpBadIOErrorLogDoneList = NULL; } EXIT(3, ("FreellegalIOAddressList!\n"));
return; }
|