Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

697 lines
17 KiB

/*++
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
DefPortReadAcpiRegister(
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
DefPortWriteAcpiRegister(
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;
}
}
USHORT
DefRegisterReadAcpiRegister(
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_REGISTER_USHORT((PUSHORT)(AcpiInformation->PM1a_BLK +
PM1_EN_OFFSET));
break;
case PM1b_ENABLE:
return READ_REGISTER_USHORT((PUSHORT)(AcpiInformation->PM1b_BLK +
PM1_EN_OFFSET));
break;
case PM1a_STATUS:
return READ_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1a_BLK +
PM1_STS_OFFSET);
break;
case PM1b_STATUS:
return READ_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1b_BLK +
PM1_STS_OFFSET);
break;
case PM1a_CONTROL:
return READ_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1a_CTRL_BLK);
break;
case PM1b_CONTROL:
return READ_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1b_CTRL_BLK);
break;
case GP_STATUS:
if (Register < AcpiInformation->Gpe0Size) {
return READ_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP0_BLK +
Register));
} else {
return READ_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP1_BLK +
Register -
AcpiInformation->Gpe0Size));
}
break;
case GP_ENABLE:
if (Register < AcpiInformation->Gpe0Size) {
return READ_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP0_ENABLE +
Register));
} else {
return READ_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP1_ENABLE +
Register -
AcpiInformation->Gpe0Size));
}
break;
case SMI_CMD:
//
// SMI_CMD is always register based.
//
return READ_PORT_UCHAR((PUCHAR)AcpiInformation->SMI_CMD);
break;
default:
break;
}
return (USHORT)-1;
}
VOID
DefRegisterWriteAcpiRegister(
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_REGISTER_USHORT((PUSHORT)(AcpiInformation->PM1a_BLK +
PM1_EN_OFFSET), Value);
break;
case PM1b_ENABLE:
WRITE_REGISTER_USHORT((PUSHORT)(AcpiInformation->PM1b_BLK +
PM1_EN_OFFSET), Value);
break;
case PM1a_STATUS:
WRITE_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1a_BLK +
PM1_STS_OFFSET, Value);
break;
case PM1b_STATUS:
WRITE_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1b_BLK +
PM1_STS_OFFSET, Value);
break;
case PM1a_CONTROL:
WRITE_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1a_CTRL_BLK, Value);
break;
case PM1b_CONTROL:
WRITE_REGISTER_USHORT((PUSHORT)AcpiInformation->PM1b_CTRL_BLK, Value);
break;
case GP_STATUS:
if (Register < AcpiInformation->Gpe0Size) {
WRITE_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP0_BLK + Register),
(UCHAR)Value);
} else {
WRITE_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP1_BLK + Register -
AcpiInformation->Gpe0Size),
(UCHAR)Value);
}
break;
case GP_ENABLE:
if (Register < AcpiInformation->Gpe0Size) {
WRITE_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP0_ENABLE +
Register),
(UCHAR)Value);
} else {
WRITE_REGISTER_UCHAR((PUCHAR)(AcpiInformation->GP1_ENABLE +
Register -
AcpiInformation->Gpe0Size),
(UCHAR)Value);
}
break;
case SMI_CMD:
//
// SMI_CMD is always register based.
//
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 = DefPortReadAcpiRegister;
PWRITE_ACPI_REGISTER AcpiWriteRegisterRoutine = DefPortWriteAcpiRegister;