Cosmos/source/Archive/Cosmos.Hardware/ACPIManager.cs

342 lines
No EOL
11 KiB
C#

using Cosmos.Kernel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Cosmos.Hardware2
{
public static class ACPIManager
{
public static bool Enabled = false;
public static bool Found = false;
public static RSD Rsd;
public static uint[] ACPITable;
public static int Version
{
get
{
if (Found)
return Rsd.Revision;
else
return 0;
}
}
[StructLayout(LayoutKind.Explicit)] public struct RSD
{
[FieldOffset(0)] public int Signature0;
[FieldOffset(4)] public int Signature1;
[FieldOffset(8)] public byte Checksum;
[FieldOffset(9)] private byte OemID0;
[FieldOffset(10)] private byte OemID1;
[FieldOffset(11)] private byte OemID2;
[FieldOffset(12)] private byte OemID3;
[FieldOffset(13)] private byte OemID4;
[FieldOffset(14)] private byte OemID5;
[FieldOffset(15)] public byte Revision;
[FieldOffset(16)] public uint RsdtAddress;
public string Signature
{
get
{
return ""; // Signature0.ToHex(8) + Signature1.ToHex(8);
}
}
public string OemID
{
get
{
return "" + (char)OemID0 + (char)OemID1 + (char)OemID2 + (char)OemID3 + (char)OemID4 + (char)OemID5;
}
}
}
[StructLayout(LayoutKind.Explicit)] public struct acpi_gen_regaddr
{
[FieldOffset(0)] public byte space_id;
[FieldOffset(1)] public byte bit_width;
[FieldOffset(2)] public byte bit_offset;
[FieldOffset(3)] public byte resv;
[FieldOffset(4)] public uint addrl;
[FieldOffset(8)] public uint addrh;
}
[StructLayout(LayoutKind.Explicit)] public struct acpi_table_header
{
[FieldOffset(0)] public byte signature0;
[FieldOffset(1)] public byte signature1;
[FieldOffset(2)] public byte signature2;
[FieldOffset(3)] public byte signature3;
[FieldOffset(4)] public uint length;
[FieldOffset(8)] public byte revision;
[FieldOffset(9)] public byte checksum;
[FieldOffset(10)] byte oem_id0;
[FieldOffset(11)] byte oem_id1;
[FieldOffset(12)] byte oem_id2;
[FieldOffset(13)] byte oem_id3;
[FieldOffset(14)] byte oem_id4;
[FieldOffset(15)] byte oem_id5;
[FieldOffset(16)] byte oem_table_id0;
[FieldOffset(17)] byte oem_table_id1;
[FieldOffset(18)] byte oem_table_id2;
[FieldOffset(19)] byte oem_table_id3;
[FieldOffset(20)] byte oem_table_id4;
[FieldOffset(21)] byte oem_table_id5;
[FieldOffset(22)] byte oem_table_id6;
[FieldOffset(23)] byte oem_table_id7;
[FieldOffset(24)] public uint oem_revision;
[FieldOffset(28)] public uint asl_compiler_id;
[FieldOffset(32)] public uint asl_compiler_revision;
public string Signature
{
get
{
return "" + (char)signature0 + (char)signature1 + (char)signature2 + (char)signature3;
}
}
public string OemID
{
get
{
return "" + (char)oem_id0 + (char)oem_id1 + (char)oem_id2 + (char)oem_id3 + (char)oem_id4 + (char)oem_id5;
}
}
public string OemTable
{
get
{
return "" + (char)oem_table_id0 + (char)oem_table_id1 + (char)oem_table_id2 + (char)oem_table_id3 + (char)oem_table_id4 + (char)oem_table_id5 + (char)oem_table_id6 + (char)oem_table_id7;
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Fadt
{
public acpi_table_header header;
public uint firmware_ctrl;
public uint dsdt;
public byte model;
public byte preferred_pm_profile;
public ushort sci_int;
public uint smi_cmd;
public byte acpi_enable;
public byte acpi_disable;
public byte s4bios_req;
public byte pstate_cnt;
public uint pm1a_evt_blk;
public uint pm1b_evt_blk;
public uint pm1a_cnt_blk;
public uint pm1b_cnt_blk;
public uint pm2_cnt_blk;
public uint pm_tmr_blk;
public uint gpe0_blk;
public uint gpe1_blk;
public byte pm1_evt_len;
public byte pm1_cnt_len;
public byte pm2_cnt_len;
public byte pm_tmr_len;
public byte gpe0_blk_len;
public byte gpe1_blk_len;
public byte gpe1_base;
public byte cst_cnt;
public ushort p_lvl2_lat;
public ushort p_lvl3_lat;
public ushort flush_size;
public ushort flush_stride;
public byte duty_offset;
public byte duty_width;
public byte day_alrm;
public byte mon_alrm;
public byte century;
public ushort iapc_boot_arch;
public byte res2;
public uint flags;
public acpi_gen_regaddr reset_reg;
public byte reset_value;
public byte res3;
public byte res4;
public byte res5;
public uint x_firmware_ctl_l;
public uint x_firmware_ctl_h;
public uint x_dsdt_l;
public uint x_dsdt_h;
public acpi_gen_regaddr x_pm1a_evt_blk;
public acpi_gen_regaddr x_pm1b_evt_blk;
public acpi_gen_regaddr x_pm1a_cnt_blk;
public acpi_gen_regaddr x_pm1b_cnt_blk;
public acpi_gen_regaddr x_pm2_cnt_blk;
public acpi_gen_regaddr x_pm_tmr_blk;
public acpi_gen_regaddr x_gpe0_blk;
public acpi_gen_regaddr x_gpe1_blk;
}
public unsafe static void Init()
{
Console.Write("Looking for ACPI...");
uint rsdp = RSDPAddress();
if (rsdp != 0)
{
Rsd = *((RSD*)rsdp);
Found = true;
//Console.WriteLine("Found Version " + Rsd.Revision + " (" + Rsd.OemID + ") @ " + rsdp.ToHex(8));
acpi_table_header* Rsdt = (acpi_table_header*)Rsd.RsdtAddress;
uint i = Rsdt->length;
i = (i - 36) / 4;
Console.WriteLine(i + " entrys found");
ACPITable = new uint[i];
uint rsdt = Rsd.RsdtAddress;
for (int j = 0; j < i; j++)
{
ACPITable[j] = *(uint*)(rsdt + 36 +j*4);
acpi_table_header* header = (acpi_table_header*)ACPITable[j];
}
Console.Read();
}
else
{
Console.WriteLine("Not Found");
}
}
public static unsafe uint RSDPAddress()
{
Console.Write("searching for acpi...searching BIOS...");
// check bios
for (uint addr = 0xE0000; addr < 0x100000; addr += 4)
if (CheckForRSDP(addr))
return addr;
Console.Write("searching EBD...");
// check extended bios
uint ebda_address = *((uint*)0x040E);
ebda_address = (ebda_address * 0x10) & 0x000fffff;
for (uint addr = ebda_address; addr < ebda_address + 1024; addr += 4)
if (CheckForRSDP(addr))
return addr;
// not found
return 0;
}
public static unsafe bool CheckForRSDP(uint addr)
{
// check signature
byte* ch = (byte*)addr;
if (*(ch++) != (byte)'R') return false;
if (*(ch++) != (byte)'S') return false;
if (*(ch++) != (byte)'D') return false;
if (*(ch++) != (byte)' ') return false;
if (*(ch++) != (byte)'P') return false;
if (*(ch++) != (byte)'T') return false;
if (*(ch++) != (byte)'R') return false;
if (*(ch++) != (byte)' ') return false;
// check checksum
byte sum = 0;
byte* check = (byte*)addr;
for (int i = 0; i < 20; i++)
sum += *(check++);
return (sum == 0);
}
// checks for a given header and validates checksum
public static unsafe bool acpiCheckHeader(int ptr, string sig)
{
byte* b = (byte*)ptr;
for (int i = 0; i < sig.Length; i++)
if (*(b++) != (byte)sig[i])
return false;
byte* checkPtr = (byte*)ptr;
int len = *(&ptr + 1);
byte check = 0;
while (0 < len--)
check += *(checkPtr++);
return (check == 0);
}
public static unsafe bool acpiEnable()
{
/*
// check if acpi is enabled
if ( (CPUBus.Read16((unsigned int) PM1a_CNT) & SCI_EN) == 0 )
{
// check if acpi can be enabled
if (SMI_CMD != 0 && ACPI_ENABLE != 0)
{
outb((unsigned int) SMI_CMD, ACPI_ENABLE); // send acpi enable command
// give 3 seconds time to enable acpi
int i;
for (i=0; i<300; i++ )
{
if ( (inw((unsigned int) PM1a_CNT) &SCI_EN) == 1 )
break;
sleep(10);
}
if (PM1b_CNT != 0)
for (; i<300; i++ )
{
if ( (inw((unsigned int) PM1b_CNT) &SCI_EN) == 1 )
break;
sleep(10);
}
if (i<300) {
wrstr("enabled acpi.\n");
return 0;
} else {
wrstr("couldn't enable acpi.\n");
return -1;
}
} else {
wrstr("no known way to enable acpi.\n");
return -1;
}
} else {
//wrstr("acpi was already enabled.\n");
return 0;
}*/
return false;
}
}
}