mirror of
https://github.com/acpica/acpica/
synced 2024-12-31 22:54:28 +03:00
ACPI 4.0: Interpreter support for IPMI.
Adds support for IPMI which is similar to SMBus and uses a bi-directional data buffer. ACPICA BZ 773. Lin Ming.
This commit is contained in:
parent
17e7c9672f
commit
64a735c120
@ -151,6 +151,7 @@ AcpiExReadDataFromField (
|
||||
ACPI_OPERAND_OBJECT *BufferDesc;
|
||||
ACPI_SIZE Length;
|
||||
void *Buffer;
|
||||
UINT32 Function;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc);
|
||||
@ -183,13 +184,27 @@ AcpiExReadDataFromField (
|
||||
}
|
||||
}
|
||||
else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||
(ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS))
|
||||
(ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
|
||||
ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI))
|
||||
{
|
||||
/*
|
||||
* This is an SMBus read. We must create a buffer to hold the data
|
||||
* and directly access the region handler.
|
||||
* This is an SMBus or IPMI read. We must create a buffer to hold
|
||||
* the data and then directly access the region handler.
|
||||
*
|
||||
* Note: Smbus protocol value is passed in upper 16-bits of Function
|
||||
*/
|
||||
BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE);
|
||||
if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)
|
||||
{
|
||||
Length = ACPI_SMBUS_BUFFER_SIZE;
|
||||
Function = ACPI_READ | (ObjDesc->Field.Attribute << 16);
|
||||
}
|
||||
else /* IPMI */
|
||||
{
|
||||
Length = ACPI_IPMI_BUFFER_SIZE;
|
||||
Function = ACPI_READ;
|
||||
}
|
||||
|
||||
BufferDesc = AcpiUtCreateBufferObject (Length);
|
||||
if (!BufferDesc)
|
||||
{
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
@ -199,13 +214,11 @@ AcpiExReadDataFromField (
|
||||
|
||||
AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
|
||||
|
||||
/*
|
||||
* Perform the read.
|
||||
* Note: Smbus protocol value is passed in upper 16-bits of Function
|
||||
*/
|
||||
/* Call the region handler for the read */
|
||||
|
||||
Status = AcpiExAccessRegion (ObjDesc, 0,
|
||||
ACPI_CAST_PTR (ACPI_INTEGER, BufferDesc->Buffer.Pointer),
|
||||
ACPI_READ | (ObjDesc->Field.Attribute << 16));
|
||||
Function);
|
||||
AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
|
||||
goto Exit;
|
||||
}
|
||||
@ -304,6 +317,7 @@ AcpiExWriteDataToField (
|
||||
UINT32 Length;
|
||||
void *Buffer;
|
||||
ACPI_OPERAND_OBJECT *BufferDesc;
|
||||
UINT32 Function;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc);
|
||||
@ -332,40 +346,59 @@ AcpiExWriteDataToField (
|
||||
}
|
||||
}
|
||||
else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||
(ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS))
|
||||
(ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
|
||||
ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI))
|
||||
{
|
||||
/*
|
||||
* This is an SMBus write. We will bypass the entire field mechanism
|
||||
* and handoff the buffer directly to the handler.
|
||||
* This is an SMBus or IPMI write. We will bypass the entire field
|
||||
* mechanism and handoff the buffer directly to the handler. For
|
||||
* these address spaces, the buffer is bi-directional; on a write,
|
||||
* return data is returned in the same buffer.
|
||||
*
|
||||
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
|
||||
* Source must be a buffer of sufficient size:
|
||||
* ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE.
|
||||
*
|
||||
* Note: SMBus protocol type is passed in upper 16-bits of Function
|
||||
*/
|
||||
if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER)
|
||||
{
|
||||
ACPI_ERROR ((AE_INFO, "SMBus write requires Buffer, found type %s",
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"SMBus or IPMI write requires Buffer, found type %s",
|
||||
AcpiUtGetObjectTypeName (SourceDesc)));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
if (SourceDesc->Buffer.Length < ACPI_SMBUS_BUFFER_SIZE)
|
||||
if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)
|
||||
{
|
||||
Length = ACPI_SMBUS_BUFFER_SIZE;
|
||||
Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16);
|
||||
}
|
||||
else /* IPMI */
|
||||
{
|
||||
Length = ACPI_IPMI_BUFFER_SIZE;
|
||||
Function = ACPI_WRITE;
|
||||
}
|
||||
|
||||
if (SourceDesc->Buffer.Length < Length)
|
||||
{
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"SMBus write requires Buffer of length %X, found length %X",
|
||||
ACPI_SMBUS_BUFFER_SIZE, SourceDesc->Buffer.Length));
|
||||
"SMBus or IPMI write requires Buffer of length %X, found length %X",
|
||||
Length, SourceDesc->Buffer.Length));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
|
||||
}
|
||||
|
||||
BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE);
|
||||
/* Create the bi-directional buffer */
|
||||
|
||||
BufferDesc = AcpiUtCreateBufferObject (Length);
|
||||
if (!BufferDesc)
|
||||
{
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
Buffer = BufferDesc->Buffer.Pointer;
|
||||
ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer,
|
||||
ACPI_SMBUS_BUFFER_SIZE);
|
||||
ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer, Length);
|
||||
|
||||
/* Lock entire transaction if requested */
|
||||
|
||||
@ -374,11 +407,9 @@ AcpiExWriteDataToField (
|
||||
/*
|
||||
* Perform the write (returns status and perhaps data in the
|
||||
* same buffer)
|
||||
* Note: SMBus protocol type is passed in upper 16-bits of Function.
|
||||
*/
|
||||
Status = AcpiExAccessRegion (ObjDesc, 0,
|
||||
(ACPI_INTEGER *) Buffer,
|
||||
ACPI_WRITE | (ObjDesc->Field.Attribute << 16));
|
||||
(ACPI_INTEGER *) Buffer, Function);
|
||||
AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
|
||||
|
||||
*ResultDesc = BufferDesc;
|
||||
|
@ -202,12 +202,13 @@ AcpiExSetupRegion (
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit now for SMBus address space, it has a non-linear address space
|
||||
* Exit now for SMBus or IPMI address space, it has a non-linear address space
|
||||
* and the request cannot be directly validated
|
||||
*/
|
||||
if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)
|
||||
if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
|
||||
RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
|
||||
{
|
||||
/* SMBus has a non-linear address space */
|
||||
/* SMBus or IPMI has a non-linear address space */
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
@ -252,9 +252,10 @@
|
||||
#define ACPI_RSDP_CHECKSUM_LENGTH 20
|
||||
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
|
||||
|
||||
/* SMBus bidirectional buffer size */
|
||||
/* SMBus and IPMI bidirectional buffer size */
|
||||
|
||||
#define ACPI_SMBUS_BUFFER_SIZE 34
|
||||
#define ACPI_IPMI_BUFFER_SIZE 66
|
||||
|
||||
/* _SxD and _SxW control methods */
|
||||
|
||||
|
@ -816,7 +816,8 @@ typedef UINT8 ACPI_ADR_SPACE_TYPE;
|
||||
#define ACPI_ADR_SPACE_SMBUS (ACPI_ADR_SPACE_TYPE) 4
|
||||
#define ACPI_ADR_SPACE_CMOS (ACPI_ADR_SPACE_TYPE) 5
|
||||
#define ACPI_ADR_SPACE_PCI_BAR_TARGET (ACPI_ADR_SPACE_TYPE) 6
|
||||
#define ACPI_ADR_SPACE_DATA_TABLE (ACPI_ADR_SPACE_TYPE) 7
|
||||
#define ACPI_ADR_SPACE_IPMI (ACPI_ADR_SPACE_TYPE) 7
|
||||
#define ACPI_ADR_SPACE_DATA_TABLE (ACPI_ADR_SPACE_TYPE) 8
|
||||
#define ACPI_ADR_SPACE_FIXED_HARDWARE (ACPI_ADR_SPACE_TYPE) 127
|
||||
|
||||
|
||||
|
@ -493,8 +493,8 @@ AeRegionInit (
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
ACPI_ADR_SPACE_TYPE SpaceId[] = {0, 1, 2, 3, 4, 5, 6, 0x80};
|
||||
#define AEXEC_NUM_REGIONS 8
|
||||
ACPI_ADR_SPACE_TYPE SpaceId[] = {0, 1, 2, 3, 4, 5, 6, 7, 0x80};
|
||||
#define AEXEC_NUM_REGIONS 9
|
||||
|
||||
ACPI_STATUS
|
||||
AeInstallHandlers (void)
|
||||
@ -630,7 +630,8 @@ AeRegionHandler (
|
||||
void *RegionContext)
|
||||
{
|
||||
|
||||
ACPI_OPERAND_OBJECT *RegionObject = (ACPI_OPERAND_OBJECT*) RegionContext;
|
||||
ACPI_OPERAND_OBJECT *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
|
||||
UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Value);
|
||||
ACPI_PHYSICAL_ADDRESS BaseAddress;
|
||||
ACPI_SIZE Length;
|
||||
BOOLEAN BufferExists;
|
||||
@ -681,8 +682,9 @@ AeRegionHandler (
|
||||
AcpiUtGetRegionName (RegionObject->Region.SpaceId),
|
||||
(UINT32) Address));
|
||||
|
||||
if (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
|
||||
switch (SpaceId)
|
||||
{
|
||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||
/*
|
||||
* For I/O space, exercise the port validation
|
||||
*/
|
||||
@ -707,10 +709,11 @@ AeRegionHandler (
|
||||
}
|
||||
|
||||
/* Now go ahead and simulate the hardware */
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_ADR_SPACE_SMBUS:
|
||||
|
||||
else if (SpaceId == ACPI_ADR_SPACE_SMBUS)
|
||||
{
|
||||
Length = 0;
|
||||
|
||||
switch (Function & ACPI_IO_MASK)
|
||||
@ -769,13 +772,37 @@ AeRegionHandler (
|
||||
|
||||
for (i = 0; i < Length; i++)
|
||||
{
|
||||
((UINT8 *) Value)[i+2] = (UINT8) (0xA0 + i);
|
||||
Buffer[i+2] = (UINT8) (0xA0 + i);
|
||||
}
|
||||
|
||||
((UINT8 *) Value)[0] = 0x7A;
|
||||
((UINT8 *) Value)[1] = (UINT8) Length;
|
||||
Buffer[0] = 0x7A;
|
||||
Buffer[1] = (UINT8) Length;
|
||||
return (AE_OK);
|
||||
|
||||
return AE_OK;
|
||||
|
||||
case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
|
||||
|
||||
AcpiOsPrintf ("AcpiExec: Received IPMI request: "
|
||||
"Address %X BaseAddress %X Length %X Width %X BufferLength %u\n",
|
||||
(UINT32) Address, (UINT32) BaseAddress,
|
||||
Length, BitWidth, Buffer[1]);
|
||||
|
||||
/*
|
||||
* Regardless of a READ or WRITE, this handler is passed a 66-byte
|
||||
* buffer in which to return the IPMI status/length/data.
|
||||
*
|
||||
* Return some example data to show use of the bidirectional buffer
|
||||
*/
|
||||
Buffer[0] = 0; /* Status byte */
|
||||
Buffer[1] = 64; /* Return buffer data length */
|
||||
Buffer[2] = 0; /* Completion code */
|
||||
Buffer[3] = 0x34; /* Power measurement */
|
||||
Buffer[4] = 0x12; /* Power measurement */
|
||||
Buffer[65] = 0xEE; /* last buffer byte */
|
||||
return (AE_OK);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user