windows-nt/Source/XPSP1/NT/base/busdrv/acpi/driver/shared/acpiio.c

510 lines
11 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;