Skip to content

Commit

Permalink
Mosa.DeviceDriver: various improvements
Browse files Browse the repository at this point in the history
Signed-off-by: AnErrupTion <[email protected]>
  • Loading branch information
AnErrupTion committed Mar 8, 2024
1 parent 347e7bf commit e73e57d
Show file tree
Hide file tree
Showing 25 changed files with 550 additions and 573 deletions.
175 changes: 84 additions & 91 deletions Source/Mosa.DeviceDriver/ISA/ACPI/ACPIDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
using Mosa.DeviceSystem.HardwareAbstraction;
using Mosa.Runtime;

namespace Mosa.DeviceDriver.ISA.ACPI;

// Portions of this code are from Cosmos

//https://wiki.osdev.org/ACPI
//https://wiki.osdev.org/MADT

namespace Mosa.DeviceDriver.ISA.ACPI;

public unsafe class ACPIDriver : BaseDeviceDriver, IACPI
public class ACPIDriver : BaseDeviceDriver, IACPI
{
private FADT FADT;
private RSDT RSDT;
private XSDT XSDT;
private MADT MADT;
private FADT fadt;
private RSDT rsdt;
private XSDT xsdt;
private MADT madt;

private IOPortWrite SMI_CommandPort;
private IOPortWrite smiCommandPort;

public short SLP_TYPa { get; set; }

Expand All @@ -45,66 +45,39 @@ public unsafe class ACPIDriver : BaseDeviceDriver, IACPI
public override void Initialize()
{
Device.Name = "ACPI";
//Setup();
}

/// <summary>
/// Probes this instance.
/// </summary>
public override void Probe() => Device.Status = DeviceStatus.Offline; // Future: Should be "Available"

/// <summary>
/// Starts this hardware device.
/// </summary>
public override void Start()
{
SMI_CommandPort.Write8(FADT.AcpiEnable);
HAL.Sleep(3000);
Device.Status = DeviceStatus.Online;
}

/// <summary>
/// Stops this hardware device.
/// </summary>
public override void Stop()
{
SMI_CommandPort.Write8(FADT.AcpiDisable);
HAL.Sleep(3000);
Device.Status = DeviceStatus.Offline;
}

private void Setup()
{
// TODO: Find the multiboot service
// Multiboot.V2.RSDPv1

var rsdp = Pointer.Zero; // HAL.GetRSDP();
var version2 = true; // HAL.IsACPIVersion2();
if (rsdp.IsNull)
return;

var version2 = true; // HAL.IsACPIVersion2();
if (version2)
{
var descriptor20 = new RSDPDescriptor20(rsdp);
XSDT = new XSDT(HAL.GetPhysicalMemory(descriptor20.XsdtAddress, 0xFFFF).Address);
xsdt = new XSDT(HAL.GetPhysicalMemory(descriptor20.XsdtAddress, 0xFFFF).Address);
}
else
{
var descriptor = new RSDPDescriptor(rsdp);
RSDT = new RSDT(HAL.GetPhysicalMemory(descriptor.RsdtAddress, 0xFFFF).Address);
rsdt = new RSDT(HAL.GetPhysicalMemory(descriptor.RsdtAddress, 0xFFFF).Address);
}

FADT = new FADT(HAL.GetPhysicalMemory(FindBySignature("FACP"), 0xFFFF).Address);
MADT = new MADT(HAL.GetPhysicalMemory(FindBySignature("APIC"), 0xFFFF).Address);
fadt = new FADT(HAL.GetPhysicalMemory(FindBySignature("FACP"), 0xFFFF).Address);
madt = new MADT(HAL.GetPhysicalMemory(FindBySignature("APIC"), 0xFFFF).Address);

if (FADT.Pointer.IsNull)
if (fadt.Pointer.IsNull)
return;

if (!MADT.Pointer.IsNull)
if (!madt.Pointer.IsNull)
{
ProcessorIDs = new byte[256];
LocalApicAddress = MADT.LocalApicAddress;
LocalApicAddress = madt.LocalApicAddress;

var ptr = MADT.Pointer;
var ptr2 = ptr + MADT.ACPISDTHeader.Length;
var ptr = madt.Pointer;
var ptr2 = ptr + madt.ACPISDTHeader.Length;

for (ptr += 0x2C; ptr < ptr2;)
{
Expand Down Expand Up @@ -135,74 +108,94 @@ private void Setup()
}
}

var dsdt = new Pointer(FADT.Dsdt);
var dsdt = new Pointer(fadt.Dsdt);
if (dsdt.Load32() != 0x54445344) return; //DSDT

if (dsdt.Load32() == 0x54445344) //DSDT
{
var S5Addr = dsdt + ACPISDTHeader.Offset.Size;
var dsdtLength = (int)dsdt.Load32() + 1 - ACPISDTHeader.Offset.Size;

for (var k = 0; k < dsdtLength; k++)
{
if (S5Addr.Load32() == 0x5f35535f)
break; //_S5_
var s5addr = dsdt + ACPISDTHeader.Offset.Size;
var dsdtLength = (int)dsdt.Load32() + 1 - ACPISDTHeader.Offset.Size;

S5Addr++;
}
for (var k = 0; k < dsdtLength; k++)
{
if (s5addr.Load32() == 0x5f35535f)
break; //_S5_

if ((dsdtLength > 0)
&& (((S5Addr - 1).Load8() == 0x08 || (S5Addr - 2).Load8() == 0x08 && (S5Addr - 1).Load8() == '\\') && (S5Addr + 4).Load8() == 0x12))
{
S5Addr += 5;
S5Addr += ((S5Addr.Load32() & 0xC0) >> 6) + 2;
s5addr++;
}

if (S5Addr.Load8() == 0x0A) S5Addr++;
if ((dsdtLength <= 0) || (((s5addr - 1).Load8() != 0x08 && ((s5addr - 2).Load8() != 0x08 || (s5addr - 1).Load8() != '\\'))
|| (s5addr + 4).Load8() != 0x12)) return;
s5addr += 5;
s5addr += ((s5addr.Load32() & 0xC0) >> 6) + 2;

SLP_TYPa = (short)(S5Addr.Load16() << 10);
S5Addr++;
if (s5addr.Load8() == 0x0A) s5addr++;

if (S5Addr.Load8() == 0x0A) S5Addr++;
SLP_TYPa = (short)(s5addr.Load16() << 10);
s5addr++;

SLP_TYPb = (short)(S5Addr.Load16() << 10);
SLP_EN = 1 << 13;
if (s5addr.Load8() == 0x0A) s5addr++;

SMI_CommandPort = new IOPortWrite((ushort)FADT.SMI_CommandPort);
SLP_TYPb = (short)(s5addr.Load16() << 10);
SLP_EN = 1 << 13;

var has64BitPtr = false;
smiCommandPort = new IOPortWrite((ushort)fadt.SMI_CommandPort);

if (version2)
{
ResetAddress = new IOPortWrite((ushort)FADT.ResetReg.Address);
ResetValue = FADT.ResetValue;
var has64BitPtr = false;

if (Pointer.Size == 8) // 64-bit
{
has64BitPtr = true;
if (version2)
{
ResetAddress = new IOPortWrite((ushort)fadt.ResetReg.Address);
ResetValue = fadt.ResetValue;

PM1aControlBlock = new IOPortWrite((ushort)FADT.X_PM1aControlBlock.Address);
if (FADT.X_PM1bControlBlock.Address != 0) PM1bControlBlock = new IOPortWrite((ushort)FADT.X_PM1bControlBlock.Address);
}
}
if (Pointer.Size == 8) // 64-bit
{
has64BitPtr = true;

if (!has64BitPtr)
{
PM1aControlBlock = new IOPortWrite((ushort)FADT.PM1aControlBlock);
if (FADT.PM1bControlBlock != 0) PM1bControlBlock = new IOPortWrite((ushort)FADT.PM1bControlBlock);
}
PM1aControlBlock = new IOPortWrite((ushort)fadt.X_PM1aControlBlock.Address);
if (fadt.X_PM1bControlBlock.Address != 0) PM1bControlBlock = new IOPortWrite((ushort)fadt.X_PM1bControlBlock.Address);
}
}

if (has64BitPtr) return;

PM1aControlBlock = new IOPortWrite((ushort)fadt.PM1aControlBlock);
if (fadt.PM1bControlBlock != 0) PM1bControlBlock = new IOPortWrite((ushort)fadt.PM1bControlBlock);
}

/// <summary>
/// Probes this instance.
/// </summary>
public override void Probe() => Device.Status = DeviceStatus.Offline; // Future: Should be "Available"

/// <summary>
/// Starts this hardware device.
/// </summary>
public override void Start()
{
smiCommandPort.Write8(fadt.AcpiEnable);
HAL.Sleep(3000);
Device.Status = DeviceStatus.Online;
}

/// <summary>
/// Stops this hardware device.
/// </summary>
public override void Stop()
{
smiCommandPort.Write8(fadt.AcpiDisable);
HAL.Sleep(3000);
Device.Status = DeviceStatus.Offline;
}

private Pointer FindBySignature(string signature)
{
var xsdt = !XSDT.Pointer.IsNull;
var hasXSDT = !xsdt.Pointer.IsNull;
var value = CalculateSignatureValue(signature);

for (var i = 0U; i < (xsdt ? 16 : 8); i++)
for (var i = 0U; i < (hasXSDT ? 16 : 8); i++)
{
// On some systems or VM software (e.g. VirtualBox), we have to map the pointer, or else it will crash.
// See: https://github.com/msareedjr/MOSA-MikeOS/commit/6867064fedae707280083ba4d9ff12d468a6dce0
var h = new ACPISDTHeader(HAL.GetPhysicalMemory(xsdt ? XSDT.GetPointerToOtherSDT(i) : RSDT.GetPointerToOtherSDT(i), 0xFFF).Address);
var h = new ACPISDTHeader(HAL.GetPhysicalMemory(hasXSDT ? xsdt.GetPointerToOtherSDT(i) : rsdt.GetPointerToOtherSDT(i), 0xFFF).Address);

if (!h.Pointer.IsNull && h.Signature == value)
return h.Pointer;
Expand Down
18 changes: 9 additions & 9 deletions Source/Mosa.DeviceDriver/ISA/ACPI/ACPISDTHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace Mosa.DeviceDriver.ISA.ACPI;

public struct ACPISDTHeader
{
public readonly Pointer Pointer;
public Pointer Pointer;

public readonly uint Size = Offset.Size;
public const uint Size = Offset.Size;

internal static class Offset
{
Expand All @@ -26,21 +26,21 @@ internal static class Offset

public ACPISDTHeader(Pointer entry) => Pointer = entry;

public readonly uint Signature => Pointer.Load32(Offset.Signature);
public uint Signature => Pointer.Load32(Offset.Signature);

public readonly uint Length => Pointer.Load32(Offset.Length);
public uint Length => Pointer.Load32(Offset.Length);

public readonly byte Revision => Pointer.Load8(Offset.Revision);
public byte Revision => Pointer.Load8(Offset.Revision);

public readonly byte Checksum => Pointer.Load8(Offset.Checksum);
public byte Checksum => Pointer.Load8(Offset.Checksum);

public byte GetOEMID(int index) => Pointer.Load8(Offset.OEMID + index);

public byte GetOEMTableID(int index) => Pointer.Load8(Offset.OEMTableID + index);

public readonly uint OEMRevision => Pointer.Load32(Offset.OEMRevision);
public uint OEMRevision => Pointer.Load32(Offset.OEMRevision);

public readonly uint CreatorID => Pointer.Load32(Offset.CreatorID);
public uint CreatorID => Pointer.Load32(Offset.CreatorID);

public readonly uint CreatorRevision => Pointer.Load32(Offset.CreatorRevision);
public uint CreatorRevision => Pointer.Load32(Offset.CreatorRevision);
}
Loading

0 comments on commit e73e57d

Please sign in to comment.