510 lines
11 KiB
C
510 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
acpiio.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
ACPI OS Independent I/O routines
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jason Clark (JasonCl)
|
|||
|
Stephane Plante (SPlante)
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
NT Kernel Model Driver only
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Eric Nelson - Add Def[ault]Read/Write routines
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
//
|
|||
|
// This driver is not in alpha or beta stages any more --- we can save some
|
|||
|
// CPU calls if we simply define the debug function to nothing
|
|||
|
//
|
|||
|
#define DebugTraceIO(Write, Port, Length, Value )
|
|||
|
static UCHAR IOTrace = 0;
|
|||
|
|
|||
|
VOID
|
|||
|
ACPIIoDebugTrace(
|
|||
|
BOOLEAN Write,
|
|||
|
PUSHORT Port,
|
|||
|
UCHAR Length,
|
|||
|
ULONG Value
|
|||
|
)
|
|||
|
{
|
|||
|
if (IOTrace != 0) {
|
|||
|
|
|||
|
ACPIPrint( (
|
|||
|
ACPI_PRINT_IO,
|
|||
|
"%x byte %s port 0x%x value %x\n",
|
|||
|
Length, Write ? "WRITE" : "READ", Port, Value
|
|||
|
) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
ACPIIoReadPm1Status(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads the PM1 Status registers and masks off any bits that
|
|||
|
we don't care about. This is done because some of these bits are actually
|
|||
|
owned by the HAL
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ULONG
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
return READ_PM1_STATUS() &
|
|||
|
(AcpiInformation->pm1_en_bits | PM1_WAK_STS | PM1_TMR_STS | PM1_RTC_STS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
CLEAR_PM1_STATUS_BITS (
|
|||
|
USHORT BitMask
|
|||
|
)
|
|||
|
{
|
|||
|
if (AcpiInformation->PM1a_BLK != 0) {
|
|||
|
|
|||
|
WRITE_ACPI_REGISTER(PM1a_STATUS, 0, BitMask);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
TRUE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1a_BLK+PM1_STS_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
BitMask
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
if (AcpiInformation->PM1b_BLK != 0) {
|
|||
|
|
|||
|
WRITE_ACPI_REGISTER(PM1b_STATUS, 0, BitMask);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
TRUE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1b_BLK+PM1_STS_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
BitMask
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
CLEAR_PM1_STATUS_REGISTER (
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT Value = 0;
|
|||
|
|
|||
|
if (AcpiInformation->PM1a_BLK != 0) {
|
|||
|
|
|||
|
Value = READ_ACPI_REGISTER(PM1a_STATUS, 0);
|
|||
|
WRITE_ACPI_REGISTER(PM1a_STATUS, 0, Value);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
TRUE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1a_BLK+PM1_STS_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
Value
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (AcpiInformation->PM1b_BLK != 0) {
|
|||
|
|
|||
|
Value = READ_ACPI_REGISTER(PM1b_STATUS, 0);
|
|||
|
WRITE_ACPI_REGISTER(PM1b_STATUS, 0, Value);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
TRUE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1b_BLK+PM1_STS_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
Value
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
USHORT
|
|||
|
READ_PM1_CONTROL(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT pm1=0;
|
|||
|
|
|||
|
if (AcpiInformation->PM1a_CTRL_BLK != 0) {
|
|||
|
|
|||
|
pm1 = READ_ACPI_REGISTER(PM1a_CONTROL, 0);
|
|||
|
|
|||
|
}
|
|||
|
if (AcpiInformation->PM1b_CTRL_BLK != 0) {
|
|||
|
|
|||
|
pm1 |= READ_ACPI_REGISTER(PM1b_CONTROL, 0);
|
|||
|
|
|||
|
}
|
|||
|
return (pm1);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
USHORT
|
|||
|
READ_PM1_ENABLE(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT pm1=0;
|
|||
|
|
|||
|
if (AcpiInformation->PM1a_BLK != 0) {
|
|||
|
|
|||
|
pm1 = READ_ACPI_REGISTER(PM1a_ENABLE, 0);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
FALSE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1a_BLK+PM1_EN_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
pm1
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
if (AcpiInformation->PM1b_BLK != 0) {
|
|||
|
|
|||
|
pm1 |= READ_ACPI_REGISTER(PM1b_ENABLE, 0);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
FALSE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1b_BLK+PM1_EN_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
pm1
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
return (pm1);
|
|||
|
}
|
|||
|
|
|||
|
USHORT
|
|||
|
READ_PM1_STATUS(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT pm1=0;
|
|||
|
|
|||
|
if (AcpiInformation->PM1a_BLK != 0) {
|
|||
|
|
|||
|
pm1 = READ_ACPI_REGISTER(PM1a_STATUS, 0);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
FALSE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1a_BLK+PM1_STS_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
pm1
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
if (AcpiInformation->PM1b_BLK != 0) {
|
|||
|
|
|||
|
pm1 |= READ_ACPI_REGISTER(PM1b_STATUS, 0);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
FALSE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1b_BLK+PM1_STS_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
pm1
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
return (pm1);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
WRITE_PM1_CONTROL(
|
|||
|
USHORT Value,
|
|||
|
BOOLEAN Destructive,
|
|||
|
ULONG Flags
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
if (!Destructive) {
|
|||
|
|
|||
|
USHORT pm1;
|
|||
|
|
|||
|
if ( (Flags & WRITE_REGISTER_A) && (AcpiInformation->PM1a_BLK != 0) ) {
|
|||
|
|
|||
|
pm1 = READ_ACPI_REGISTER(PM1a_CONTROL, 0);
|
|||
|
pm1 |= Value;
|
|||
|
WRITE_ACPI_REGISTER(PM1a_CONTROL, 0, pm1);
|
|||
|
|
|||
|
}
|
|||
|
if ( (Flags & WRITE_REGISTER_B) && (AcpiInformation->PM1b_BLK != 0) ) {
|
|||
|
|
|||
|
pm1 = READ_ACPI_REGISTER(PM1b_CONTROL, 0);
|
|||
|
pm1 |= Value;
|
|||
|
WRITE_ACPI_REGISTER(PM1b_CONTROL, 0, pm1);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// clear this bit and the system dies
|
|||
|
// it is legit when called by the ACPI shutdown code
|
|||
|
// which will use the WRITE_SCI flag.
|
|||
|
//
|
|||
|
ASSERT ( (Flags & WRITE_SCI) || (Value & PM1_SCI_EN) );
|
|||
|
|
|||
|
if ( (Flags & WRITE_REGISTER_A) && (AcpiInformation->PM1a_BLK != 0) ) {
|
|||
|
|
|||
|
WRITE_ACPI_REGISTER(PM1a_CONTROL, 0, Value);
|
|||
|
|
|||
|
}
|
|||
|
if ( (Flags & WRITE_REGISTER_B) && (AcpiInformation->PM1b_BLK != 0) ) {
|
|||
|
|
|||
|
WRITE_ACPI_REGISTER(PM1b_CONTROL, 0, Value);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
WRITE_PM1_ENABLE(
|
|||
|
USHORT Value
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
if (AcpiInformation->PM1a_BLK != 0) {
|
|||
|
|
|||
|
WRITE_ACPI_REGISTER(PM1a_ENABLE, 0, Value);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
TRUE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1a_BLK+PM1_EN_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
Value
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
if (AcpiInformation->PM1b_BLK != 0) {
|
|||
|
|
|||
|
WRITE_ACPI_REGISTER(PM1b_ENABLE, 0, Value);
|
|||
|
|
|||
|
DebugTraceIO(
|
|||
|
TRUE,
|
|||
|
(PUSHORT)(AcpiInformation->PM1b_BLK+PM1_EN_OFFSET),
|
|||
|
sizeof(USHORT),
|
|||
|
Value
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
USHORT
|
|||
|
DefReadAcpiRegister(
|
|||
|
ACPI_REG_TYPE AcpiReg,
|
|||
|
ULONG Register
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified ACPI fixed register.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AcpiReg - Specifies which ACPI fixed register to read from.
|
|||
|
|
|||
|
Register - Specifies which GP register to read from. Not used for PM1x
|
|||
|
registers.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Value of the specified ACPI fixed register.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
switch (AcpiReg) {
|
|||
|
|
|||
|
case PM1a_ENABLE:
|
|||
|
return READ_PORT_USHORT((PUSHORT)(AcpiInformation->PM1a_BLK +
|
|||
|
PM1_EN_OFFSET));
|
|||
|
break;
|
|||
|
|
|||
|
case PM1b_ENABLE:
|
|||
|
return READ_PORT_USHORT((PUSHORT)(AcpiInformation->PM1b_BLK +
|
|||
|
PM1_EN_OFFSET));
|
|||
|
break;
|
|||
|
|
|||
|
case PM1a_STATUS:
|
|||
|
return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_BLK +
|
|||
|
PM1_STS_OFFSET);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1b_STATUS:
|
|||
|
return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_BLK +
|
|||
|
PM1_STS_OFFSET);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1a_CONTROL:
|
|||
|
return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_CTRL_BLK);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1b_CONTROL:
|
|||
|
return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_CTRL_BLK);
|
|||
|
break;
|
|||
|
|
|||
|
case GP_STATUS:
|
|||
|
if (Register < AcpiInformation->Gpe0Size) {
|
|||
|
return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_BLK +
|
|||
|
Register));
|
|||
|
} else {
|
|||
|
return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_BLK +
|
|||
|
Register -
|
|||
|
AcpiInformation->Gpe0Size));
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case GP_ENABLE:
|
|||
|
if (Register < AcpiInformation->Gpe0Size) {
|
|||
|
return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_ENABLE +
|
|||
|
Register));
|
|||
|
} else {
|
|||
|
return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_ENABLE +
|
|||
|
Register -
|
|||
|
AcpiInformation->Gpe0Size));
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SMI_CMD:
|
|||
|
return READ_PORT_UCHAR((PUCHAR)AcpiInformation->SMI_CMD);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return (USHORT)-1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DefWriteAcpiRegister(
|
|||
|
ACPI_REG_TYPE AcpiReg,
|
|||
|
ULONG Register,
|
|||
|
USHORT Value
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Write to the specified ACPI fixed register.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AcpiReg - Specifies which ACPI fixed register to write to.
|
|||
|
|
|||
|
Register - Specifies which GP register to write to. Not used for PM1x
|
|||
|
registers.
|
|||
|
|
|||
|
Value - Data to write.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
switch (AcpiReg) {
|
|||
|
|
|||
|
case PM1a_ENABLE:
|
|||
|
WRITE_PORT_USHORT((PUSHORT)(AcpiInformation->PM1a_BLK +
|
|||
|
PM1_EN_OFFSET), Value);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1b_ENABLE:
|
|||
|
WRITE_PORT_USHORT((PUSHORT)(AcpiInformation->PM1b_BLK +
|
|||
|
PM1_EN_OFFSET), Value);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1a_STATUS:
|
|||
|
WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_BLK +
|
|||
|
PM1_STS_OFFSET, Value);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1b_STATUS:
|
|||
|
WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_BLK +
|
|||
|
PM1_STS_OFFSET, Value);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1a_CONTROL:
|
|||
|
WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_CTRL_BLK, Value);
|
|||
|
break;
|
|||
|
|
|||
|
case PM1b_CONTROL:
|
|||
|
WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_CTRL_BLK, Value);
|
|||
|
break;
|
|||
|
|
|||
|
case GP_STATUS:
|
|||
|
if (Register < AcpiInformation->Gpe0Size) {
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_BLK + Register),
|
|||
|
(UCHAR)Value);
|
|||
|
} else {
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_BLK + Register -
|
|||
|
AcpiInformation->Gpe0Size),
|
|||
|
(UCHAR)Value);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case GP_ENABLE:
|
|||
|
if (Register < AcpiInformation->Gpe0Size) {
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_ENABLE +
|
|||
|
Register),
|
|||
|
(UCHAR)Value);
|
|||
|
} else {
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_ENABLE +
|
|||
|
Register -
|
|||
|
AcpiInformation->Gpe0Size),
|
|||
|
(UCHAR)Value);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SMI_CMD:
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)AcpiInformation->SMI_CMD, (UCHAR)Value);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// READ/WRITE_ACPI_REGISTER macros are implemented via these
|
|||
|
// function pointers
|
|||
|
//
|
|||
|
PREAD_ACPI_REGISTER AcpiReadRegisterRoutine = DefReadAcpiRegister;
|
|||
|
PWRITE_ACPI_REGISTER AcpiWriteRegisterRoutine = DefWriteAcpiRegister;
|