12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- oprgn.c
- Abstract:
- This module implements support for ACPI Operation Regions.
- Author:
- Evan Green 17-Nov-2012
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include "acpiobj.h"
- #include "amlos.h"
- #include "namespce.h"
- #include "oprgn.h"
- #include "fixedreg.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- VOID
- AcpipShiftBufferIntoFieldPosition (
- PVOID Buffer,
- ULONGLONG BitOffset,
- ULONGLONG BitLength,
- ULONG AccessSize
- );
- VOID
- AcpipWriteFieldBitsIntoBuffer (
- PVOID FieldBuffer,
- ULONGLONG BitOffset,
- ULONGLONG BitLength,
- ULONG AccessSize,
- PVOID ResultBuffer,
- ULONGLONG ResultBufferSize
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- AcpipCreateOperationRegion (
- PAML_EXECUTION_CONTEXT Context,
- PSTR Name,
- ACPI_OPERATION_REGION_SPACE Space,
- ULONGLONG Offset,
- ULONGLONG Length
- )
- /*++
- Routine Description:
- This routine creates an ACPI Operation Region object.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- Name - Supplies a pointer to the name of the Operation Region object.
- Space - Supplies the address space type of the region.
- Offset - Supplies the byte offset into the address space of the beginning
- of the Operation Region.
- Length - Supplies the byte length of the Operation Region.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OPERATION_REGION_FUNCTION_TABLE FunctionTable;
- PACPI_OBJECT Object;
- PVOID OsContext;
- PVOID OsMutex;
- KSTATUS Status;
- FunctionTable = NULL;
- Object = NULL;
- OsContext = NULL;
- OsMutex = NULL;
- //
- // Get a pointer to the operation region function table.
- //
- if (Space >= OperationRegionCount) {
- Status = STATUS_INVALID_PARAMETER;
- goto CreateOperationRegionEnd;
- }
- //
- // Create the namespace object.
- //
- Object = AcpipCreateNamespaceObject(Context,
- AcpiObjectOperationRegion,
- Name,
- NULL,
- 0);
- if (Object == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto CreateOperationRegionEnd;
- }
- AcpipObjectReleaseReference(Object);
- //
- // Create the mutex.
- //
- OsMutex = AcpipCreateMutex(0);
- if (OsMutex == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto CreateOperationRegionEnd;
- }
- FunctionTable = AcpiOperationRegionFunctionTable[Space];
- //
- // Create the operation region with the OS.
- //
- Status = FunctionTable->Create(Object, Offset, Length, &OsContext);
- if (!KSUCCESS(Status)) {
- goto CreateOperationRegionEnd;
- }
- //
- // Initialize and return the operation region.
- //
- Object->U.OperationRegion.Space = Space;
- Object->U.OperationRegion.OsContext = OsContext;
- Object->U.OperationRegion.Offset = Offset;
- Object->U.OperationRegion.Length = Length;
- Object->U.OperationRegion.FunctionTable = FunctionTable;
- Object->U.OperationRegion.OsMutex = OsMutex;
- Status = STATUS_SUCCESS;
- CreateOperationRegionEnd:
- if (!KSUCCESS(Status)) {
- //
- // Destroy the operation region if created.
- //
- if (OsContext != NULL) {
- FunctionTable->Destroy(OsContext);
- }
- //
- // Destroy the mutex.
- //
- if (OsMutex != NULL) {
- AcpipDestroyMutex(OsMutex);
- }
- if (Object != NULL) {
- AcpipObjectReleaseReference(Object);
- }
- }
- return Status;
- }
- VOID
- AcpipDestroyOperationRegion (
- PACPI_OBJECT Object
- )
- /*++
- Routine Description:
- This routine destroys an ACPI Operation Region object. This routine should
- not be called directly, but will be called from the namespace object
- destruction routine.
- Arguments:
- Object - Supplies a pointer to the operation region to destroy.
- Return Value:
- None.
- --*/
- {
- PACPI_OPERATION_REGION_FUNCTION_TABLE FunctionTable;
- ASSERT(Object->Type == AcpiObjectOperationRegion);
- if (Object->U.OperationRegion.OsContext != NULL) {
- FunctionTable = Object->U.OperationRegion.FunctionTable;
- ASSERT(FunctionTable != NULL);
- FunctionTable->Destroy(Object->U.OperationRegion.OsContext);
- Object->U.OperationRegion.OsContext = NULL;
- }
- if (Object->U.OperationRegion.OsMutex != NULL) {
- AcpipDestroyMutex(Object->U.OperationRegion.OsMutex);
- Object->U.OperationRegion.OsMutex = NULL;
- }
- Object->U.OperationRegion.FunctionTable = NULL;
- return;
- }
- KSTATUS
- AcpipReadFromField (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT FieldObject,
- PACPI_OBJECT *ResultObject
- )
- /*++
- Routine Description:
- This routine reads from an Operation Region field.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- FieldObject - Supplies a pointer to the field object to read from.
- ResultObject - Supplies a pointer where a pointer to the result object will
- be returned. The caller is responsible for freeing this memory.
- Return Value:
- STATUS_SUCCESS on success.
- Error codes on failure.
- --*/
- {
- ULONG AccessSize;
- PACPI_OBJECT AlternateOperationRegion;
- BOOL AlternateOperationRegionMutexAcquired;
- PACPI_OBJECT BankRegister;
- ULONGLONG BufferSize;
- PUCHAR CurrentBuffer;
- ULONGLONG CurrentOffset;
- PACPI_OBJECT DataRegister;
- PACPI_OBJECT DataResult;
- ULONGLONG EndBitOffset;
- ULONGLONG EndByteOffset;
- PACPI_FIELD_UNIT_OBJECT FieldUnit;
- BOOL GlobalLockAcquired;
- PACPI_OBJECT IndexRegister;
- PACPI_OBJECT IndexValue;
- BOOL IntegerWidthIs32;
- PACPI_OPERATION_REGION_OBJECT OperationRegion;
- BOOL OperationRegionMutexHeld;
- PACPI_OBJECT OperationRegionObject;
- PACPI_OBJECT Result;
- PUCHAR ResultBuffer;
- ULONGLONG StartBitOffset;
- ULONGLONG StartByteOffset;
- KSTATUS Status;
- *ResultObject = NULL;
- AlternateOperationRegion = NULL;
- AlternateOperationRegionMutexAcquired = FALSE;
- BankRegister = NULL;
- GlobalLockAcquired = FALSE;
- IndexValue = NULL;
- OperationRegion = NULL;
- OperationRegionMutexHeld = FALSE;
- Result = NULL;
- FieldUnit = &(FieldObject->U.FieldUnit);
- ASSERT(FieldObject->Type == AcpiObjectFieldUnit);
- OperationRegionObject = FieldUnit->OperationRegion;
- if (OperationRegionObject != NULL) {
- ASSERT(OperationRegionObject->Type == AcpiObjectOperationRegion);
- OperationRegion = &(OperationRegionObject->U.OperationRegion);
- }
- switch (FieldUnit->Access) {
- case AcpiFieldAccessAny:
- case AcpiFieldAccessBuffer:
- case AcpiFieldAccessByte:
- AccessSize = BITS_PER_BYTE;
- break;
- case AcpiFieldAccessWord:
- AccessSize = 2 * BITS_PER_BYTE;
- break;
- case AcpiFieldAccessDoubleWord:
- AccessSize = 4 * BITS_PER_BYTE;
- break;
- case AcpiFieldAccessQuadWord:
- AccessSize = 8 * BITS_PER_BYTE;
- break;
- default:
- ASSERT(FALSE);
- Status = STATUS_INVALID_PARAMETER;
- goto ReadFromFieldEnd;
- }
- //
- // Calculate the size of the buffer needed by rounding the offset down
- // to the access size, and the length up.
- //
- StartBitOffset = ALIGN_RANGE_DOWN(FieldUnit->BitOffset, AccessSize);
- EndBitOffset = ALIGN_RANGE_UP(FieldUnit->BitOffset + FieldUnit->BitLength,
- AccessSize);
- BufferSize = (EndBitOffset - StartBitOffset) / BITS_PER_BYTE;
- StartByteOffset = StartBitOffset / BITS_PER_BYTE;
- EndByteOffset = EndBitOffset / BITS_PER_BYTE;
- //
- // Allocate the result buffer. Use an integer if the result is small
- // enough to fit in one, or create a buffer if not.
- //
- IntegerWidthIs32 = FALSE;
- if (Context->CurrentMethod != NULL) {
- IntegerWidthIs32 = Context->CurrentMethod->IntegerWidthIs32;
- }
- if ((BufferSize <= sizeof(ULONG)) ||
- ((IntegerWidthIs32 == FALSE) && (BufferSize <= sizeof(ULONGLONG)))) {
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (Result == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto ReadFromFieldEnd;
- }
- Result->U.Integer.Value = 0;
- ResultBuffer = (PUCHAR)&(Result->U.Integer.Value);
- } else {
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- BufferSize);
- if (Result == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto ReadFromFieldEnd;
- }
- ResultBuffer = Result->U.Buffer.Buffer;
- RtlZeroMemory(ResultBuffer, BufferSize);
- }
- //
- // Validate that the reads are safe.
- //
- if (OperationRegion != NULL) {
- if ((StartByteOffset > OperationRegion->Length) ||
- (EndByteOffset > OperationRegion->Length) ||
- (EndByteOffset <= StartByteOffset)) {
- Status = STATUS_INVALID_PARAMETER;
- goto ReadFromFieldEnd;
- }
- }
- //
- // If the field is banked, acquire the mutex for the Operation Region that
- // the bank register points at, and write the bank value to the bank
- // register.
- //
- BankRegister = FieldUnit->BankRegister;
- IndexRegister = FieldUnit->IndexRegister;
- DataRegister = FieldUnit->DataRegister;
- if (BankRegister != NULL) {
- ASSERT(BankRegister->Type == AcpiObjectFieldUnit);
- AlternateOperationRegion = BankRegister->U.FieldUnit.OperationRegion;
- ASSERT(AlternateOperationRegion->Type == AcpiObjectOperationRegion);
- AcpipAcquireMutex(Context,
- AlternateOperationRegion->U.OperationRegion.OsMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- AlternateOperationRegionMutexAcquired = TRUE;
- //
- // Store the bank value into the bank register.
- //
- Status = AcpipPerformStoreOperation(Context,
- FieldUnit->BankValue,
- BankRegister);
- if (!KSUCCESS(Status)) {
- goto ReadFromFieldEnd;
- }
- //
- // If the field is Indexed, acquire the mutex for the Operation Region
- // that the Index register points at.
- //
- } else if (IndexRegister != NULL) {
- ASSERT(IndexRegister->Type == AcpiObjectFieldUnit);
- AlternateOperationRegion = IndexRegister->U.FieldUnit.OperationRegion;
- ASSERT(AlternateOperationRegion->Type == AcpiObjectOperationRegion);
- AcpipAcquireMutex(Context,
- AlternateOperationRegion->U.OperationRegion.OsMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- AlternateOperationRegionMutexAcquired = TRUE;
- //
- // Also create the index value variable at this time.
- //
- IndexValue = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (IndexValue == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto ReadFromFieldEnd;
- }
- }
- //
- // Acquire the mutex and global lock if needed.
- //
- if (OperationRegion != NULL) {
- AcpipAcquireMutex(Context,
- OperationRegion->OsMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- OperationRegionMutexHeld = TRUE;
- }
- if (FieldUnit->AcquireGlobalLock != FALSE) {
- AcpipAcquireGlobalLock();
- GlobalLockAcquired = TRUE;
- }
- //
- // Perform the reads.
- //
- Status = STATUS_SUCCESS;
- CurrentBuffer = ResultBuffer;
- for (CurrentOffset = StartByteOffset;
- CurrentOffset < EndByteOffset;
- CurrentOffset += (AccessSize / BITS_PER_BYTE)) {
- //
- // For indexed fields, write the index value, then read from the data
- // register.
- //
- if (IndexRegister != NULL) {
- IndexValue->U.Integer.Value = CurrentOffset;
- Status = AcpipWriteToField(Context, IndexRegister, IndexValue);
- if (!KSUCCESS(Status)) {
- break;
- }
- Status = AcpipReadFromField(Context, DataRegister, &DataResult);
- if (!KSUCCESS(Status)) {
- break;
- }
- //
- // Copy the result from the read into the destination buffer.
- //
- if (DataResult->Type == AcpiObjectInteger) {
- RtlCopyMemory(CurrentBuffer,
- &(DataResult->U.Integer.Value),
- AccessSize);
- } else if (DataResult->Type == AcpiObjectBuffer) {
- RtlCopyMemory(CurrentBuffer,
- DataResult->U.Buffer.Buffer,
- AccessSize);
- } else {
- AcpipObjectReleaseReference(DataResult);
- Status = STATUS_INVALID_PARAMETER;
- goto ReadFromFieldEnd;
- }
- AcpipObjectReleaseReference(DataResult);
- //
- // Perform a normal region read.
- //
- } else {
- Status = OperationRegion->FunctionTable->Read(
- OperationRegion->OsContext,
- CurrentOffset,
- AccessSize,
- CurrentBuffer);
- if (!KSUCCESS(Status)) {
- //
- // Allow region access that occur before they're supposed to.
- //
- if (Status == STATUS_TOO_EARLY) {
- RtlZeroMemory(CurrentBuffer, AccessSize / BITS_PER_BYTE);
- Status = STATUS_SUCCESS;
- } else {
- break;
- }
- }
- }
- CurrentBuffer += AccessSize / BITS_PER_BYTE;
- }
- if (GlobalLockAcquired != FALSE) {
- AcpipReleaseGlobalLock();
- GlobalLockAcquired = FALSE;
- }
- if (OperationRegionMutexHeld != FALSE) {
- AcpipReleaseMutex(Context, OperationRegion->OsMutex);
- OperationRegionMutexHeld = FALSE;
- }
- //
- // If something in the loop failed, bail now.
- //
- if (!KSUCCESS(Status)) {
- goto ReadFromFieldEnd;
- }
- //
- // Shift the buffer, which was read naturally aligned, into the position
- // dictated by the field.
- //
- AcpipShiftBufferIntoFieldPosition(ResultBuffer,
- FieldUnit->BitOffset,
- FieldUnit->BitLength,
- AccessSize);
- ReadFromFieldEnd:
- if (GlobalLockAcquired != FALSE) {
- AcpipReleaseGlobalLock();
- }
- if (OperationRegionMutexHeld != FALSE) {
- AcpipReleaseMutex(Context, OperationRegion->OsMutex);
- }
- //
- // Release the alternate mutex if acquired.
- //
- if (AlternateOperationRegionMutexAcquired != FALSE) {
- AcpipReleaseMutex(Context,
- AlternateOperationRegion->U.OperationRegion.OsMutex);
- }
- if (IndexValue != NULL) {
- AcpipObjectReleaseReference(IndexValue);
- }
- if (!KSUCCESS(Status)) {
- if (Result != NULL) {
- AcpipObjectReleaseReference(Result);
- Result = NULL;
- }
- }
- *ResultObject = Result;
- return Status;
- }
- KSTATUS
- AcpipWriteToField (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT FieldObject,
- PACPI_OBJECT ValueToWrite
- )
- /*++
- Routine Description:
- This routine writes to an Operation Region field.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- FieldObject - Supplies a pointer to the field object to write to.
- ValueToWrite - Supplies a pointer to an Integer or Buffer object containing
- the value to write into the field.
- Return Value:
- STATUS_SUCCESS on success.
- Error codes on failure.
- --*/
- {
- ULONG AccessSize;
- PACPI_OBJECT AlternateOperationRegion;
- BOOL AlternateOperationRegionMutexAcquired;
- PACPI_OBJECT BankRegister;
- ULONGLONG BufferSize;
- PUCHAR CurrentBuffer;
- ULONGLONG CurrentOffset;
- PACPI_OBJECT DataRegister;
- PACPI_OBJECT DataResult;
- ULONGLONG EndBitOffset;
- ULONGLONG EndByteOffset;
- ULONGLONG FieldByteLength;
- PACPI_FIELD_UNIT_OBJECT FieldUnit;
- PACPI_OBJECT IndexRegister;
- PACPI_OBJECT IndexValue;
- BOOL IntegerWidthIs32;
- BOOL LocksHeld;
- PACPI_OPERATION_REGION_OBJECT OperationRegion;
- PACPI_OBJECT OperationRegionObject;
- PACPI_OBJECT Result;
- PUCHAR ResultBuffer;
- PUCHAR SourceBuffer;
- ULONGLONG SourceBufferSize;
- ULONGLONG StartBitOffset;
- ULONGLONG StartByteOffset;
- KSTATUS Status;
- AlternateOperationRegion = NULL;
- AlternateOperationRegionMutexAcquired = FALSE;
- BankRegister = NULL;
- DataRegister = NULL;
- DataResult = NULL;
- IndexRegister = NULL;
- IndexValue = NULL;
- LocksHeld = FALSE;
- OperationRegion = NULL;
- Result = NULL;
- FieldUnit = &(FieldObject->U.FieldUnit);
- ASSERT(FieldObject->Type == AcpiObjectFieldUnit);
- OperationRegionObject = FieldUnit->OperationRegion;
- if (OperationRegionObject != NULL) {
- ASSERT(OperationRegionObject->Type == AcpiObjectOperationRegion);
- OperationRegion = &(OperationRegionObject->U.OperationRegion);
- }
- switch (FieldUnit->Access) {
- case AcpiFieldAccessAny:
- case AcpiFieldAccessBuffer:
- case AcpiFieldAccessByte:
- AccessSize = BITS_PER_BYTE;
- break;
- case AcpiFieldAccessWord:
- AccessSize = 2 * BITS_PER_BYTE;
- break;
- case AcpiFieldAccessDoubleWord:
- AccessSize = 4 * BITS_PER_BYTE;
- break;
- case AcpiFieldAccessQuadWord:
- AccessSize = 8 * BITS_PER_BYTE;
- break;
- default:
- ASSERT(FALSE);
- Status = STATUS_INVALID_PARAMETER;
- goto WriteToFieldEnd;
- }
- //
- // Calculate the size of the buffer needed by rounding the offset down
- // to the access size, and the length up.
- //
- StartBitOffset = ALIGN_RANGE_DOWN(FieldUnit->BitOffset, AccessSize);
- EndBitOffset = ALIGN_RANGE_UP(FieldUnit->BitOffset + FieldUnit->BitLength,
- AccessSize);
- BufferSize = (EndBitOffset - StartBitOffset) / BITS_PER_BYTE;
- StartByteOffset = StartBitOffset / BITS_PER_BYTE;
- EndByteOffset = EndBitOffset / BITS_PER_BYTE;
- //
- // Allocate the result buffer. Use an integer if the result is small
- // enough to fit in one, or create a buffer if not.
- //
- IntegerWidthIs32 = FALSE;
- if (Context->CurrentMethod != NULL) {
- IntegerWidthIs32 = Context->CurrentMethod->IntegerWidthIs32;
- }
- if ((BufferSize <= sizeof(ULONG)) ||
- ((IntegerWidthIs32 == FALSE) && (BufferSize <= sizeof(ULONGLONG)))) {
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (Result == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto WriteToFieldEnd;
- }
- ResultBuffer = (PUCHAR)&(Result->U.Integer.Value);
- } else {
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- BufferSize);
- if (Result == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto WriteToFieldEnd;
- }
- ResultBuffer = Result->U.Buffer.Buffer;
- }
- //
- // Validate that the accesses are safe.
- //
- if (OperationRegion != NULL) {
- if ((StartByteOffset >= OperationRegion->Length) ||
- (EndByteOffset > OperationRegion->Length) ||
- (EndByteOffset <= StartByteOffset)) {
- Status = STATUS_INVALID_PARAMETER;
- goto WriteToFieldEnd;
- }
- }
- //
- // Determine the source buffer based on the source object.
- //
- if (ValueToWrite->Type == AcpiObjectInteger) {
- SourceBuffer = (PUCHAR)&(ValueToWrite->U.Integer.Value);
- SourceBufferSize = sizeof(ULONGLONG);
- if (IntegerWidthIs32 != FALSE) {
- SourceBufferSize = sizeof(ULONG);
- }
- } else if (ValueToWrite->Type == AcpiObjectBuffer) {
- SourceBuffer = ValueToWrite->U.Buffer.Buffer;
- SourceBufferSize = ValueToWrite->U.Buffer.Length;
- } else {
- Status = STATUS_NOT_SUPPORTED;
- goto WriteToFieldEnd;
- }
- //
- // The source buffer needs to be at least the size of the field.
- //
- FieldByteLength = ALIGN_RANGE_UP(FieldUnit->BitLength, BITS_PER_BYTE) /
- BITS_PER_BYTE;
- if (SourceBufferSize < FieldByteLength) {
- Status = STATUS_BUFFER_OVERRUN;
- goto WriteToFieldEnd;
- }
- //
- // If the field is banked, acquire the mutex for the Operation Region that
- // the bank register points at, and write the bank value to the bank
- // register.
- //
- BankRegister = FieldUnit->BankRegister;
- IndexRegister = FieldUnit->IndexRegister;
- DataRegister = FieldUnit->DataRegister;
- if (BankRegister != NULL) {
- ASSERT(BankRegister->Type == AcpiObjectFieldUnit);
- AlternateOperationRegion = BankRegister->U.FieldUnit.OperationRegion;
- ASSERT(AlternateOperationRegion->Type == AcpiObjectOperationRegion);
- AcpipAcquireMutex(Context,
- AlternateOperationRegion->U.OperationRegion.OsMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- AlternateOperationRegionMutexAcquired = TRUE;
- //
- // Store the bank value into the bank register.
- //
- Status = AcpipPerformStoreOperation(Context,
- FieldUnit->BankValue,
- BankRegister);
- if (!KSUCCESS(Status)) {
- goto WriteToFieldEnd;
- }
- //
- // If the field is Indexed, acquire the mutex for the Operation Region
- // that the Index register points at.
- //
- } else if (IndexRegister != NULL) {
- ASSERT(IndexRegister->Type == AcpiObjectFieldUnit);
- AlternateOperationRegion = IndexRegister->U.FieldUnit.OperationRegion;
- ASSERT(AlternateOperationRegion->Type == AcpiObjectOperationRegion);
- AcpipAcquireMutex(Context,
- AlternateOperationRegion->U.OperationRegion.OsMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- AlternateOperationRegionMutexAcquired = TRUE;
- //
- // Also create the index value variable at this time.
- //
- IndexValue = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (IndexValue == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto WriteToFieldEnd;
- }
- }
- //
- // Acquire the mutex and global lock if needed. Do this now because if the
- // rule is preserve, then the register should be read/modified/written
- // atomically.
- //
- if (OperationRegion != NULL) {
- AcpipAcquireMutex(Context,
- OperationRegion->OsMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- }
- if (FieldUnit->AcquireGlobalLock != FALSE) {
- AcpipAcquireGlobalLock();
- }
- LocksHeld = TRUE;
- //
- // Fill up the buffer with an initial value depending on the update rule.
- // If the field is already aligned, then there's no need for the read
- // (and it can in fact be harmful if it has side effects).
- //
- if ((StartBitOffset != FieldUnit->BitOffset) ||
- (EndBitOffset != FieldUnit->BitOffset + FieldUnit->BitLength)) {
- CurrentBuffer = ResultBuffer;
- if (FieldUnit->UpdateRule == AcpiFieldUpdatePreserve) {
- for (CurrentOffset = StartByteOffset;
- CurrentOffset < EndByteOffset;
- CurrentOffset += (AccessSize / BITS_PER_BYTE)) {
- //
- // For indexed fields, write the index value, then read from
- // the data register.
- //
- if (IndexRegister != NULL) {
- IndexValue->U.Integer.Value = CurrentOffset;
- Status = AcpipWriteToField(Context,
- IndexRegister,
- IndexValue);
- if (!KSUCCESS(Status)) {
- goto WriteToFieldEnd;
- }
- Status = AcpipReadFromField(Context,
- DataRegister,
- &DataResult);
- if (!KSUCCESS(Status)) {
- goto WriteToFieldEnd;
- }
- //
- // Copy the result from the read into the destination
- // buffer.
- //
- if (DataResult->Type == AcpiObjectInteger) {
- RtlCopyMemory(CurrentBuffer,
- &(DataResult->U.Integer.Value),
- AccessSize);
- } else if (DataResult->Type == AcpiObjectBuffer) {
- RtlCopyMemory(CurrentBuffer,
- DataResult->U.Buffer.Buffer,
- AccessSize);
- } else {
- Status = STATUS_INVALID_PARAMETER;
- goto WriteToFieldEnd;
- }
- AcpipObjectReleaseReference(DataResult);
- DataResult = NULL;
- //
- // Perform a normal region read.
- //
- } else {
- Status = OperationRegion->FunctionTable->Read(
- OperationRegion->OsContext,
- CurrentOffset,
- AccessSize,
- CurrentBuffer);
- if (!KSUCCESS(Status)) {
- break;
- }
- }
- CurrentBuffer += AccessSize / BITS_PER_BYTE;
- }
- } else if (FieldUnit->UpdateRule == AcpiFieldUpdateWriteAsOnes) {
- for (CurrentOffset = StartByteOffset;
- CurrentOffset < EndByteOffset;
- CurrentOffset += (AccessSize / BITS_PER_BYTE)) {
- *CurrentBuffer = 0xFF;
- CurrentBuffer += 1;
- }
- } else {
- RtlZeroMemory(CurrentBuffer, EndByteOffset - StartByteOffset);
- }
- }
- //
- // Modify the result buffer to include the bits being set in the field.
- //
- AcpipWriteFieldBitsIntoBuffer(SourceBuffer,
- FieldUnit->BitOffset,
- FieldUnit->BitLength,
- AccessSize,
- ResultBuffer,
- BufferSize);
- //
- // If it's an Index/Data style write, create an index data value now.
- //
- if (IndexRegister != NULL) {
- DataResult = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (DataResult == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto WriteToFieldEnd;
- }
- }
- //
- // Perform the writes.
- //
- CurrentBuffer = ResultBuffer;
- for (CurrentOffset = StartByteOffset;
- CurrentOffset < EndByteOffset;
- CurrentOffset += (AccessSize / BITS_PER_BYTE)) {
- //
- // For indexed fields, write the index value, then read from the data
- // register.
- //
- if (IndexRegister != NULL) {
- IndexValue->U.Integer.Value = CurrentOffset;
- Status = AcpipWriteToField(Context, IndexRegister, IndexValue);
- if (!KSUCCESS(Status)) {
- goto WriteToFieldEnd;
- }
- DataResult->U.Integer.Value = 0;
- RtlCopyMemory(&(DataResult->U.Integer.Value),
- CurrentBuffer,
- AccessSize);
- Status = AcpipWriteToField(Context, DataRegister, DataResult);
- if (!KSUCCESS(Status)) {
- goto WriteToFieldEnd;
- }
- //
- // Perform a normal region write.
- //
- } else {
- Status = OperationRegion->FunctionTable->Write(
- OperationRegion->OsContext,
- CurrentOffset,
- AccessSize,
- CurrentBuffer);
- if (!KSUCCESS(Status)) {
- goto WriteToFieldEnd;
- }
- }
- CurrentBuffer += AccessSize / BITS_PER_BYTE;
- }
- Status = STATUS_SUCCESS;
- WriteToFieldEnd:
- if (LocksHeld != FALSE) {
- if (FieldUnit->AcquireGlobalLock != FALSE) {
- AcpipReleaseGlobalLock();
- }
- if (OperationRegion != NULL) {
- AcpipReleaseMutex(Context, OperationRegion->OsMutex);
- }
- }
- //
- // Release the alternate mutex if acquired.
- //
- if (AlternateOperationRegionMutexAcquired != FALSE) {
- AcpipReleaseMutex(Context,
- AlternateOperationRegion->U.OperationRegion.OsMutex);
- }
- if (IndexValue != NULL) {
- AcpipObjectReleaseReference(IndexValue);
- }
- if (DataResult != NULL) {
- AcpipObjectReleaseReference(DataResult);
- }
- if (Result != NULL) {
- AcpipObjectReleaseReference(Result);
- Result = NULL;
- }
- return Status;
- }
- KSTATUS
- AcpipReadFromBufferField (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT BufferField,
- PACPI_OBJECT *ResultObject
- )
- /*++
- Routine Description:
- This routine reads from a Buffer Field.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- BufferField - Supplies a pointer to the field object to read from.
- ResultObject - Supplies a pointer where a pointer to the result object will
- be returned. The caller is responsible for freeing this memory.
- Return Value:
- STATUS_SUCCESS on success.
- Error codes on failure.
- --*/
- {
- ULONGLONG BaseBufferSize;
- PVOID BasePointer;
- PACPI_OBJECT BufferObject;
- ULONGLONG EndBitOffset;
- ULONGLONG EndByteOffset;
- BOOL IntegerWidthIs32;
- PACPI_OBJECT Result;
- PVOID ResultBuffer;
- ULONGLONG ResultBufferSize;
- ULONGLONG StartBitOffset;
- ULONGLONG StartByteOffset;
- KSTATUS Status;
- ASSERT(BufferField->Type == AcpiObjectBufferField);
- Result = NULL;
- //
- // Find the buffer this field points to.
- //
- BufferObject = BufferField->U.BufferField.DestinationObject;
- switch (BufferObject->Type) {
- case AcpiObjectInteger:
- BasePointer = &(BufferObject->U.Integer.Value);
- BaseBufferSize = sizeof(ULONGLONG);
- break;
- case AcpiObjectString:
- BasePointer = &(BufferObject->U.String.String);
- if (BasePointer == NULL) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto ReadFromBufferFieldEnd;
- }
- BaseBufferSize = RtlStringLength(BasePointer) + 1;
- break;
- case AcpiObjectBuffer:
- BasePointer = BufferObject->U.Buffer.Buffer;
- BaseBufferSize = BufferObject->U.Buffer.Length;
- if (BaseBufferSize == 0) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto ReadFromBufferFieldEnd;
- }
- break;
- default:
- ASSERT(FALSE);
- Status = STATUS_NOT_SUPPORTED;
- goto ReadFromBufferFieldEnd;
- }
- //
- // Perform access checks on the field.
- //
- StartBitOffset = ALIGN_RANGE_DOWN(BufferField->U.BufferField.BitOffset,
- BITS_PER_BYTE);
- StartByteOffset = StartBitOffset / BITS_PER_BYTE;
- EndBitOffset = BufferField->U.BufferField.BitOffset +
- BufferField->U.BufferField.BitLength;
- EndBitOffset = ALIGN_RANGE_UP(EndBitOffset, BITS_PER_BYTE);
- EndByteOffset = EndBitOffset / BITS_PER_BYTE;
- ResultBufferSize = EndByteOffset - StartByteOffset;
- if ((StartByteOffset > BaseBufferSize) ||
- (EndByteOffset > BaseBufferSize) ||
- (EndByteOffset <= StartByteOffset)) {
- Status = STATUS_INVALID_PARAMETER;
- goto ReadFromBufferFieldEnd;
- }
- //
- // Allocate the result buffer.
- //
- IntegerWidthIs32 = FALSE;
- if (Context->CurrentMethod != NULL) {
- IntegerWidthIs32 = Context->CurrentMethod->IntegerWidthIs32;
- }
- if ((ResultBufferSize <= sizeof(ULONG)) ||
- ((ResultBufferSize <= sizeof(ULONGLONG)) &&
- (IntegerWidthIs32 != FALSE))) {
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (Result == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto ReadFromBufferFieldEnd;
- }
- Result->U.Integer.Value = 0;
- ResultBuffer = &(Result->U.Integer.Value);
- } else {
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- ResultBufferSize);
- if (Result == NULL) {
- Status = STATUS_UNSUCCESSFUL;
- goto ReadFromBufferFieldEnd;
- }
- ResultBuffer = Result->U.Buffer.Buffer;
- }
- //
- // Copy the naturally aligned memory to the destination.
- //
- RtlCopyMemory(ResultBuffer,
- BasePointer + StartByteOffset,
- EndByteOffset - StartByteOffset);
- //
- // Shift the memory into place.
- //
- AcpipShiftBufferIntoFieldPosition(ResultBuffer,
- BufferField->U.BufferField.BitOffset,
- BufferField->U.BufferField.BitLength,
- BITS_PER_BYTE);
- Status = STATUS_SUCCESS;
- ReadFromBufferFieldEnd:
- if (!KSUCCESS(Status)) {
- if (Result != NULL) {
- AcpipObjectReleaseReference(Result);
- Result = NULL;
- }
- }
- *ResultObject = Result;
- return Status;
- }
- KSTATUS
- AcpipWriteToBufferField (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT BufferField,
- PACPI_OBJECT ValueToWrite
- )
- /*++
- Routine Description:
- This routine reads from a Buffer Field.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- BufferField - Supplies a pointer to the field object to read from.
- ValueToWrite - Supplies a pointer to the value to write to the buffer field.
- Return Value:
- STATUS_SUCCESS on success.
- Error codes on failure.
- --*/
- {
- PACPI_OBJECT BufferObject;
- PVOID DestinationBuffer;
- ULONGLONG DestinationBufferSize;
- ULONGLONG EndBitOffset;
- ULONGLONG EndByteOffset;
- PVOID FieldBuffer;
- ULONGLONG FieldBufferSize;
- ULONGLONG StartBitOffset;
- ULONGLONG StartByteOffset;
- KSTATUS Status;
- ASSERT(BufferField->Type == AcpiObjectBufferField);
- //
- // Find the buffer this field points to.
- //
- BufferObject = BufferField->U.BufferField.DestinationObject;
- switch (BufferObject->Type) {
- case AcpiObjectInteger:
- DestinationBuffer = &(BufferObject->U.Integer.Value);
- DestinationBufferSize = sizeof(ULONGLONG);
- break;
- case AcpiObjectString:
- DestinationBuffer = &(BufferObject->U.String.String);
- if (DestinationBuffer == NULL) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto WriteToBufferFieldEnd;
- }
- DestinationBufferSize = RtlStringLength(DestinationBuffer) + 1;
- break;
- case AcpiObjectBuffer:
- DestinationBuffer = BufferObject->U.Buffer.Buffer;
- DestinationBufferSize = BufferObject->U.Buffer.Length;
- if (DestinationBufferSize == 0) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto WriteToBufferFieldEnd;
- }
- break;
- default:
- ASSERT(FALSE);
- Status = STATUS_NOT_SUPPORTED;
- goto WriteToBufferFieldEnd;
- }
- //
- // Find the buffer pointer of the value to write.
- //
- switch (ValueToWrite->Type) {
- case AcpiObjectInteger:
- FieldBuffer = &(ValueToWrite->U.Integer.Value);
- FieldBufferSize = sizeof(ULONGLONG);
- break;
- case AcpiObjectString:
- FieldBuffer = &(ValueToWrite->U.String.String);
- if (FieldBuffer == NULL) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto WriteToBufferFieldEnd;
- }
- FieldBufferSize = RtlStringLength(FieldBuffer) + 1;
- break;
- case AcpiObjectBuffer:
- FieldBuffer = ValueToWrite->U.Buffer.Buffer;
- FieldBufferSize = ValueToWrite->U.Buffer.Length;
- if (FieldBufferSize == 0) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto WriteToBufferFieldEnd;
- }
- break;
- default:
- ASSERT(FALSE);
- Status = STATUS_NOT_SUPPORTED;
- goto WriteToBufferFieldEnd;
- }
- //
- // Perform access checks on the field.
- //
- StartBitOffset = ALIGN_RANGE_DOWN(BufferField->U.BufferField.BitOffset,
- BITS_PER_BYTE);
- StartByteOffset = StartBitOffset / BITS_PER_BYTE;
- EndBitOffset = BufferField->U.BufferField.BitOffset +
- BufferField->U.BufferField.BitLength;
- EndBitOffset = ALIGN_RANGE_UP(EndBitOffset, BITS_PER_BYTE);
- EndByteOffset = EndBitOffset / BITS_PER_BYTE;
- if ((StartByteOffset > DestinationBufferSize) ||
- (EndByteOffset > DestinationBufferSize) ||
- (EndByteOffset <= StartByteOffset)) {
- Status = STATUS_INVALID_PARAMETER;
- goto WriteToBufferFieldEnd;
- }
- if (EndByteOffset - StartByteOffset > FieldBufferSize) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto WriteToBufferFieldEnd;
- }
- //
- // Write the field's bits into the destination buffer.
- //
- AcpipWriteFieldBitsIntoBuffer(FieldBuffer,
- BufferField->U.BufferField.BitOffset,
- BufferField->U.BufferField.BitLength,
- BITS_PER_BYTE,
- DestinationBuffer + StartByteOffset,
- DestinationBufferSize - StartByteOffset);
- Status = STATUS_SUCCESS;
- WriteToBufferFieldEnd:
- return Status;
- }
- VOID
- AcpipPrintOperationRegion (
- PACPI_OBJECT OperationRegion
- )
- /*++
- Routine Description:
- This routine prints a description of the given Operation Region to the
- debugger.
- Arguments:
- OperationRegion - Supplies a pointer to the Operation Region to print.
- Return Value:
- None.
- --*/
- {
- PSTR Name;
- PSTR Space;
- ASSERT(OperationRegion->Type == AcpiObjectOperationRegion);
- Space = "UnknownSpace";
- switch (OperationRegion->U.OperationRegion.Space) {
- case OperationRegionSystemMemory:
- Space = "SystemMemory";
- break;
- case OperationRegionSystemIo:
- Space = "SystemIO";
- break;
- case OperationRegionPciConfig:
- Space = "PCIConfig";
- break;
- case OperationRegionEmbeddedController:
- Space = "EmbeddedController";
- break;
- case OperationRegionSmBus:
- Space = "SMBus";
- break;
- case OperationRegionCmos:
- Space = "CMOS";
- break;
- case OperationRegionPciBarTarget:
- Space = "PCIBarTarget";
- break;
- case OperationRegionIpmi:
- Space = "IPMI";
- break;
- default:
- break;
- }
- Name = (PSTR)&(OperationRegion->Name);
- RtlDebugPrint("OperationRegion (%c%c%c%c, %s, 0x%I64x, 0x%I64x)",
- Name[0],
- Name[1],
- Name[2],
- Name[3],
- Space,
- OperationRegion->U.OperationRegion.Offset,
- OperationRegion->U.OperationRegion.Length);
- return;
- }
- VOID
- AcpipPrintFieldUnit (
- PACPI_OBJECT FieldUnit
- )
- /*++
- Routine Description:
- This routine prints a description of the given Field Unit to the
- debugger.
- Arguments:
- FieldUnit - Supplies a pointer to the Field Unit to print.
- Return Value:
- None.
- --*/
- {
- PSTR FieldUnitType;
- PSTR Name;
- FieldUnitType = "FieldUnit";
- if (FieldUnit->U.FieldUnit.BankRegister != NULL) {
- FieldUnitType = "BankField";
- }
- if (FieldUnit->U.FieldUnit.IndexRegister != NULL) {
- FieldUnitType = "IndexField";
- }
- Name = (PSTR)&(FieldUnit->Name);
- RtlDebugPrint("%s (%c%c%c%c, ",
- FieldUnitType,
- Name[0],
- Name[1],
- Name[2],
- Name[3]);
- switch (FieldUnit->U.FieldUnit.Access) {
- case AcpiFieldAccessAny:
- RtlDebugPrint("AccessAny, ");
- break;
- case AcpiFieldAccessByte:
- RtlDebugPrint("AccessByte, ");
- break;
- case AcpiFieldAccessWord:
- RtlDebugPrint("AccessWord, ");
- break;
- case AcpiFieldAccessDoubleWord:
- RtlDebugPrint("AccessDWord, ");
- break;
- case AcpiFieldAccessQuadWord:
- RtlDebugPrint("AccessQWord, ");
- break;
- case AcpiFieldAccessBuffer:
- RtlDebugPrint("AccessBuffer, ");
- break;
- default:
- RtlDebugPrint("INVALIDACCESS %d, ", FieldUnit->U.FieldUnit.Access);
- break;
- }
- if (FieldUnit->U.FieldUnit.AcquireGlobalLock == FALSE) {
- RtlDebugPrint("No");
- }
- RtlDebugPrint("Lock, ");
- switch (FieldUnit->U.FieldUnit.UpdateRule) {
- case AcpiFieldUpdatePreserve:
- RtlDebugPrint("Preserve, ");
- break;
- case AcpiFieldUpdateWriteAsOnes:
- RtlDebugPrint("WriteAsOnes, ");
- break;
- case AcpiFieldUpdateWriteAsZeros:
- RtlDebugPrint("WriteAsZeros, ");
- break;
- default:
- RtlDebugPrint("INVALIDUPDATERULE %d",
- FieldUnit->U.FieldUnit.UpdateRule);
- break;
- }
- RtlDebugPrint("%I64d)", FieldUnit->U.FieldUnit.BitLength);
- return;
- }
- VOID
- AcpipPrintBufferField (
- PACPI_OBJECT BufferField
- )
- /*++
- Routine Description:
- This routine prints a description of the given Buffer Field to the
- debugger.
- Arguments:
- BufferField - Supplies a pointer to the Buffer Field to print.
- Return Value:
- None.
- --*/
- {
- PSTR Name;
- Name = (PSTR)&(BufferField->Name);
- RtlDebugPrint("BufferField (%c%c%c%c, %I64x, %I64x, 0x%08x)",
- Name[0],
- Name[1],
- Name[2],
- Name[3],
- BufferField->U.BufferField.BitOffset,
- BufferField->U.BufferField.BitLength,
- BufferField->U.BufferField.DestinationObject);
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- AcpipShiftBufferIntoFieldPosition (
- PVOID Buffer,
- ULONGLONG BitOffset,
- ULONGLONG BitLength,
- ULONG AccessSize
- )
- /*++
- Routine Description:
- This routine shifts a naturally aligned buffer into a field result buffer.
- Arguments:
- Buffer - Supplies a pointer to the source (and destination buffer) to
- shift right.
- BitOffset - Supplies the bit offset of the field. The entire buffer will
- be shifted this many bits right.
- BitLength - Supplies the bit length of the field. Bits after this length
- will be cleared.
- AccessSize - Supplies the access size of the field in bits.
- Return Value:
- None.
- --*/
- {
- ULONGLONG BufferSize;
- PUCHAR CurrentBuffer;
- ULONGLONG CurrentOffset;
- ULONGLONG EndBitOffset;
- ULONGLONG EndByteOffset;
- ULONG Mask;
- ULONG SaveBits;
- ULONG ShiftAmount;
- ULONGLONG StartBitOffset;
- ULONGLONG StartByteOffset;
- ULONG TotalShiftAmount;
- //
- // Shift the results into place if the field is not aligned to the access
- // size.
- //
- StartBitOffset = ALIGN_RANGE_DOWN(BitOffset, AccessSize);
- EndBitOffset = ALIGN_RANGE_UP(BitOffset + BitLength, AccessSize);
- StartByteOffset = StartBitOffset / BITS_PER_BYTE;
- EndByteOffset = EndBitOffset / BITS_PER_BYTE;
- BufferSize = (EndBitOffset - StartBitOffset) / BITS_PER_BYTE;
- TotalShiftAmount = BitOffset - StartBitOffset;
- while (TotalShiftAmount != 0) {
- //
- // Since the shift algorithm deals in byte pointers (so as not to
- // overstep the array), the max that can be shifted in one iteration is
- // an entire byte.
- //
- if (TotalShiftAmount > BITS_PER_BYTE) {
- ShiftAmount = BITS_PER_BYTE;
- } else {
- ShiftAmount = TotalShiftAmount;
- }
- TotalShiftAmount -= ShiftAmount;
- CurrentBuffer = Buffer;
- for (CurrentOffset = 0;
- CurrentOffset < BufferSize - 1;
- CurrentOffset += 1) {
- *CurrentBuffer = (*CurrentBuffer >> ShiftAmount) |
- (*(CurrentBuffer + 1) << (BITS_PER_BYTE - ShiftAmount));
- CurrentBuffer += 1;
- }
- //
- // Do the last one, filled with zeroes.
- //
- *CurrentBuffer = *CurrentBuffer >> ShiftAmount;
- }
- //
- // Clip the unwanted portion on the end of the buffer. Remember that the
- // buffer has already been shifted down by the unaligned bit offset. For
- // example, if the bit field started at bit 1 with a length of 1, then
- // after the right shift of one that has already occurred, 1 bit needs to
- // be saved (and 7 zeroed).
- //
- SaveBits = BitLength & (AccessSize - 1);
- if (SaveBits != 0) {
- CurrentBuffer = Buffer +
- (EndByteOffset - StartByteOffset) -
- (AccessSize / BITS_PER_BYTE);
- for (CurrentOffset = 0;
- CurrentOffset < (AccessSize / BITS_PER_BYTE);
- CurrentOffset += 1) {
- if (SaveBits > BITS_PER_BYTE) {
- SaveBits -= BITS_PER_BYTE;
- } else {
- //
- // Create a mask that has ones for each bit to save, and zeroes
- // for the more significant parts.
- //
- Mask = (1 << SaveBits) - 1;
- *CurrentBuffer &= Mask;
- SaveBits = 0;
- }
- CurrentBuffer += 1;
- }
- }
- return;
- }
- VOID
- AcpipWriteFieldBitsIntoBuffer (
- PVOID FieldBuffer,
- ULONGLONG BitOffset,
- ULONGLONG BitLength,
- ULONG AccessSize,
- PVOID ResultBuffer,
- ULONGLONG ResultBufferSize
- )
- /*++
- Routine Description:
- This routine modifies a result buffer to write the bits from a field into
- it.
- Arguments:
- FieldBuffer - Supplies a pointer to the bit-aligned field buffer.
- BitOffset - Supplies the bit offset from the start of the region
- where this field refers to.
- BitLength - Supplies the size, in bits, of this field. It is assumed that
- the buffer is at least as big as the number of bits in the field
- rounded up to the nearest byte.
- AccessSize - Supplies the access granularity of the result buffer. The
- bit offset rounded down to the access size determines the start bit
- offset of the result buffer (which is assumed to not be the entire
- region).
- ResultBuffer - Supplies a pointer to the buffer, which is assumed to begin
- at the bit offset of the field, rounded down to the nearest access size.
- ResultBufferSize - Supplies the size of the result buffer, in bytes.
- Return Value:
- None.
- --*/
- {
- ULONG AccessSizeRemainder;
- ULONG ByteBitOffset;
- UCHAR CurrentByte;
- UCHAR Data;
- PUCHAR DestinationBuffer;
- ULONGLONG DestinationOffset;
- BOOL ExtraByte;
- UCHAR Mask;
- UCHAR PreviousByteLeftovers;
- ULONG SaveBits;
- PUCHAR SourceBuffer;
- ULONGLONG SourceBufferSize;
- ULONGLONG SourceIndex;
- ULONGLONG StartBitOffset;
- SourceBuffer = FieldBuffer;
- DestinationBuffer = ResultBuffer;
- StartBitOffset = ALIGN_RANGE_DOWN(BitOffset, AccessSize);
- AccessSizeRemainder = (BitOffset - StartBitOffset) / BITS_PER_BYTE;
- ByteBitOffset = (BitOffset - StartBitOffset) & (BITS_PER_BYTE - 1);
- //
- // Align the source buffer size up to the nearest byte of the field.
- //
- SourceBufferSize = ALIGN_RANGE_UP(BitLength, BITS_PER_BYTE) / BITS_PER_BYTE;
- //
- // Determine if there are more destination bytes to write than source bytes
- // provided due to the shifting of the source bits.
- //
- ExtraByte = FALSE;
- if ((ByteBitOffset != 0) &&
- (ALIGN_RANGE_UP(BitLength, BITS_PER_BYTE) <
- ALIGN_RANGE_UP(BitLength + ByteBitOffset, BITS_PER_BYTE))) {
- ExtraByte = TRUE;
- }
- //
- // Read the bits out of the value to write and put them in the result
- // buffer.
- //
- PreviousByteLeftovers = 0;
- for (SourceIndex = 0; SourceIndex < SourceBufferSize; SourceIndex += 1) {
- Data = SourceBuffer[SourceIndex];
- Mask = 0xFF;
- //
- // If the byte's bit offset is not zero, then extra logic needs to
- // apply to include the bits that may get left shifted away.
- //
- if (ByteBitOffset != 0) {
- CurrentByte = Data;
- Data <<= ByteBitOffset;
- //
- // If this is the first byte in the source, there is no previous
- // data to OR into it. Start the mask at the byte's bit offset.
- //
- if (SourceIndex == 0) {
- Mask <<= ByteBitOffset;
- //
- // Otherwise, OR in the bits taken from the previous byte in the
- // source buffer. The mask should be the full byte, unless this is
- // the last byte to write (handled below).
- //
- } else {
- Data |= PreviousByteLeftovers;
- }
- //
- // Some of the bits may have been shifted out of this round. Save
- // the leftovers.
- //
- PreviousByteLeftovers = CurrentByte >>
- (BITS_PER_BYTE - ByteBitOffset);
- }
- //
- // If this is the last byte in the source buffer, potentially clip the
- // mask.
- //
- if ((ExtraByte == FALSE) &&
- (((SourceIndex + 1) * BITS_PER_BYTE) > BitLength)) {
- SaveBits = (BitOffset + BitLength) & (BITS_PER_BYTE - 1);
- Mask &= (1 << SaveBits) - 1;
- }
- //
- // Mask in the appropriate bits to the result buffer.
- //
- DestinationOffset = SourceIndex + AccessSizeRemainder;
- ASSERT(DestinationOffset < ResultBufferSize);
- DestinationBuffer[DestinationOffset] =
- (DestinationBuffer[DestinationOffset] & (~Mask)) | (Data & Mask);
- }
- //
- // Write the extra byte if necessary. The bits are stored in the previous
- // byte's leftovers.
- //
- if (ExtraByte != FALSE) {
- Data = PreviousByteLeftovers;
- SaveBits = (BitOffset + BitLength) & (BITS_PER_BYTE - 1);
- ASSERT(SaveBits != 0);
- Mask = 0xFF & ((1 << SaveBits) - 1);
- DestinationOffset = SourceBufferSize + AccessSizeRemainder;
- ASSERT(DestinationOffset < ResultBufferSize);
- DestinationBuffer[DestinationOffset] =
- (DestinationBuffer[DestinationOffset] & (~Mask)) | (Data & Mask);
- }
- return;
- }
|