shilohh
Moderator
- Joined
- Jan 1, 2012
- Messages
- 1,752
- Motherboard
- Asus Prime Z490-A
- CPU
- i9-10850K
- Graphics
- RX 5700 XT
- Mac
- Mobile Phone
The following is based on my Asus X79 Rampage IV Extreme and Rampage IV Black Edition.
Background
Both boards exhibit the issue that Device USBE (2nd USB 2.0 controller) wont load. The cause of this issue is that Device HPET (High Precision Event Timer) grabs Interrupt 21 (15 Hex) preventing USBE from using it. My Asus HPET devices use 20, 21, 11 and 12 (Hex 14, 15, 0B and 0C) and the device does not specify which IRQs to use in the DSDT.
The real Mac HPET uses 2, 8, 11 and 12 but only specifies 0 and 8 in the DSDT.
My goal was to get my Asus HPET to use the same IRQs as the real Mac. When I give my Asus HPET the same IRQs as as the Mac HPET (0 and 8), it still doesn't use 2 like the Mac does.
I also had to remove 0 from Device TMR:
And 8 from RTC0:
And then I removed 2 from Device PIC, and HPET then uses 2.
To make sure that HPET wouldn't grab anything else random, I gave it 11 and 12:
Now both USB 2.0 devices load and I haven't had an issue since.
A while ago, based on RivoGirl's and PikeRAlpha's tiny SSDT examples, I started using SSDTs to inject, disable and modify devices in the OEM Asus ACPI tables (DSDT and SSDTs). I considered using SSDTs to replace all the patching I had done in the DSDT but the HPET device held me back. I asked some who understand the programming better than me if I could give HPET IRQs via SSDT and they said no. Based on my knowledge, you cant disable/hide a device and add it back without renaming it and HPET wont work with a different name. I asked myself why use any SSDTs because, if I have to patch anything in the DSDT, why not just do everything in the DSDT? However, I decided to keep using SSDTs for PCI cards and some devices that you would want to work from the very first boot (Wifi, LAN and more). I always thought it would be nice to use SSDTs for all ACPI patching as updating the BIOS and changing, moving or removing PCI cards requires the DSDT to re-extracted and patched again. It finally dawned on me to disable the DSDT's HPET and inject the patched one at a new location from a SSDT. With a new device path, I wouldn't have to rename it to inject it as a new device.
The SSDT
I disabled the HPET with:
I added it back in a new chid device of PCI0 (PCI1) with this:
Note that I had to add "Name (HPTC, 0xFED1F404)" from the DSDT because an external reference wouldn't solve a compilation error.
I had to do the same with TMR, RTC0 and PIC. I disabled them with:
I added the patched devices back in their same device path with new names matching the real Mac DSDT device names.
Here is a full example of a SSDT that fixes my IRQ conflict. However, I use the code as part of a much bigger SSDT.
Background
Both boards exhibit the issue that Device USBE (2nd USB 2.0 controller) wont load. The cause of this issue is that Device HPET (High Precision Event Timer) grabs Interrupt 21 (15 Hex) preventing USBE from using it. My Asus HPET devices use 20, 21, 11 and 12 (Hex 14, 15, 0B and 0C) and the device does not specify which IRQs to use in the DSDT.
Code:
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
_Y24)
})
OperationRegion (HCNT, SystemMemory, HPTC, 0x04)
Field (HCNT, DWordAcc, NoLock, Preserve)
{
HPTS, 2,
, 5,
HPTE, 1
}
Method (_STA, 0, NotSerialized)
{
If (HPTE)
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
Method (_CRS, 0, NotSerialized)
{
CreateDWordField (CRS, \_SB.PCI0.HPET._Y24._BAS, HTBS)
Multiply (HPTS, 0x1000, Local0)
Add (Local0, 0xFED00000, HTBS)
Return (CRS)
}
}
The real Mac HPET uses 2, 8, 11 and 12 but only specifies 0 and 8 in the DSDT.
Code:
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (_CID, EisaId ("PNP0C01"))
Name (BUF0, ResourceTemplate ()
{
[COLOR=#008000] IRQNoFlags ()
{0}
IRQNoFlags ()
{8}[/COLOR]
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
)
})
Method (_STA, 0, NotSerialized)
{
If (LGreaterEqual (OSYS, 0x07D1))
{
If (HPAE)
{
Return (0x0F)
}
}
Else
{
If (HPAE)
{
Return (0x0B)
}
}
Return (0x00)
}
Method (_CRS, 0, Serialized)
{
If (HPAE)
{
CreateDWordField (BUF0, 0x0A, HPT0)
If (LEqual (HPAS, 0x01))
{
Store (0xFED01000, HPT0)
}
If (LEqual (HPAS, 0x02))
{
Store (0xFED02000, HPT0)
}
If (LEqual (HPAS, 0x03))
{
Store (0xFED03000, HPT0)
}
}
Return (BUF0)
}
}
My goal was to get my Asus HPET to use the same IRQs as the real Mac. When I give my Asus HPET the same IRQs as as the Mac HPET (0 and 8), it still doesn't use 2 like the Mac does.
Code:
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (CRS, ResourceTemplate ()
{
[COLOR=#008000] IRQNoFlags ()
{0}
IRQNoFlags ()
{8}[/COLOR]
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
_Y24)
})
OperationRegion (HCNT, SystemMemory, HPTC, 0x04)
Field (HCNT, DWordAcc, NoLock, Preserve)
{
HPTS, 2,
, 5,
HPTE, 1
}
Method (_STA, 0, NotSerialized)
{
If (HPTE)
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
Method (_CRS, 0, NotSerialized)
{
CreateDWordField (CRS, \_SB.PCI0.HPET._Y24._BAS, HTBS)
Multiply (HPTS, 0x1000, Local0)
Add (Local0, 0xFED00000, HTBS)
Return (CRS)
}
}
I also had to remove 0 from Device TMR:
Code:
Device (TMR)
{
Name (_HID, EisaId ("PNP0100"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0040, // Range Minimum
0x0040, // Range Maximum
0x00, // Alignment
0x04, // Length
)
[COLOR=#ff0000] IRQNoFlags ()
{0}[/COLOR]
})
}
And 8 from RTC0:
Code:
Device (RTC0)
{
Name (_HID, EisaId ("PNP0B00"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0070, // Range Minimum
0x0070, // Range Maximum
0x00, // Alignment
0x02, // Length
)
[COLOR=#ff0000] IRQNoFlags ()
{8}[/COLOR]
})
}
And then I removed 2 from Device PIC, and HPET then uses 2.
Code:
Device (PIC)
{
Name (_HID, EisaId ("PNP0000"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0020, // Range Minimum
0x0020, // Range Maximum
0x00, // Alignment
0x02, // Length
)
IO (Decode16,
0x00A0, // Range Minimum
0x00A0, // Range Maximum
0x00, // Alignment
0x02, // Length
)
[COLOR=#ff0000] IRQNoFlags ()
{2}[/COLOR]
})
}
To make sure that HPET wouldn't grab anything else random, I gave it 11 and 12:
Code:
Name (CRS, ResourceTemplate ()
{
IRQNoFlags ()
{0}
IRQNoFlags ()
{8}
[COLOR=#008000] IRQNoFlags ()
{11}
IRQNoFlags ()
{12}[/COLOR]
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
_Y24)
})
A while ago, based on RivoGirl's and PikeRAlpha's tiny SSDT examples, I started using SSDTs to inject, disable and modify devices in the OEM Asus ACPI tables (DSDT and SSDTs). I considered using SSDTs to replace all the patching I had done in the DSDT but the HPET device held me back. I asked some who understand the programming better than me if I could give HPET IRQs via SSDT and they said no. Based on my knowledge, you cant disable/hide a device and add it back without renaming it and HPET wont work with a different name. I asked myself why use any SSDTs because, if I have to patch anything in the DSDT, why not just do everything in the DSDT? However, I decided to keep using SSDTs for PCI cards and some devices that you would want to work from the very first boot (Wifi, LAN and more). I always thought it would be nice to use SSDTs for all ACPI patching as updating the BIOS and changing, moving or removing PCI cards requires the DSDT to re-extracted and patched again. It finally dawned on me to disable the DSDT's HPET and inject the patched one at a new location from a SSDT. With a new device path, I wouldn't have to rename it to inject it as a new device.
The SSDT
I disabled the HPET with:
Code:
External (\_SB_.PCI0.HPET._STA, MethodObj) // 0 Arguments
Scope (_SB)
{
Method (_INI, 0, NotSerialized)
{
Store (Zero, \_SB.PCI0.HPET._STA)
}
}
I added it back in a new chid device of PCI0 (PCI1) with this:
Code:
Device (\_SB.PCI0.[COLOR=#008000]PCI1[/COLOR])
{
Name (_ADR, One)
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (CRS, ResourceTemplate ()
{
IRQNoFlags ()
{0}
IRQNoFlags ()
{8}
IRQNoFlags ()
{11}
IRQNoFlags ()
{12}
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
_Y00)
})
Name (HPTC, 0xFED1F404)
OperationRegion (HCNT, SystemMemory, HPTC, 0x04)
Field (HCNT, DWordAcc, NoLock, Preserve)
{
HPTS, 2,
, 5,
HPTE, 1
}
Method (_STA, 0, NotSerialized)
{
If (HPTE)
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
Method (_CRS, 0, NotSerialized)
{
CreateDWordField (CRS, \_SB.PCI0.PCI1.HPET._Y00._BAS, HTBS)
Multiply (HPTS, 0x1000, Local0)
Add (Local0, 0xFED00000, HTBS)
Return (CRS)
}
}
}
I had to do the same with TMR, RTC0 and PIC. I disabled them with:
Code:
Name (_SB.PCI0.SBRG.TMR._STA, Zero)
Name (_SB.PCI0.SBRG.RTC0._STA, Zero)
Name (_SB.PCI0.SBRG.PIC._STA, Zero)
I added the patched devices back in their same device path with new names matching the real Mac DSDT device names.
Code:
Device (_SB.PCI0.SBRG.TIMR)
{
Name (_HID, EisaId ("PNP0100"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0040, // Range Minimum
0x0040, // Range Maximum
0x00, // Alignment
0x04, // Length
)
})
}
Device (_SB.PCI0.SBRG.RTC)
{
Name (_HID, EisaId ("PNP0B00"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0070, // Range Minimum
0x0070, // Range Maximum
0x01, // Alignment
0x08, // Length
)
})
}
Device (_SB.PCI0.SBRG.IPIC)
{
Name (_HID, EisaId ("PNP0000"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0020, // Range Minimum
0x0020, // Range Maximum
0x00, // Alignment
0x02, // Length
)
IO (Decode16,
0x00A0, // Range Minimum
0x00A0, // Range Maximum
0x00, // Alignment
0x02, // Length
)
})
}
Here is a full example of a SSDT that fixes my IRQ conflict. However, I use the code as part of a much bigger SSDT.
Code:
/*
* Intel ACPI Component Architecture
* AML Disassembler version 20100331
*
* Disassembly of iASLFavXp7.aml, Sun Apr 17 00:57:29 2016
*
*
* Original Table Header:
* Signature "SSDT"
* Length 0x0000020B (523)
* Revision 0x01
* Checksum 0x31
* OEM ID "shiloh"
* OEM Table ID "HPET_IRQ"
* OEM Revision 0x00001000 (4096)
* Compiler ID "INTL"
* Compiler Version 0x20100331 (537920305)
*/
DefinitionBlock ("iASLFavXp7.aml", "SSDT", 1, "shiloh", "HPET_IRQ", 0x00001000)
{
External (\_SB_.PCI0.HPET._STA)
Scope (_SB)
{
Method (_INI, 0, NotSerialized)
{
Store (Zero, \_SB.PCI0.HPET._STA)
}
}
Device (\_SB.PCI0.PCI1)
{
Name (_ADR, One)
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (CRS, ResourceTemplate ()
{
IRQNoFlags ()
{0}
IRQNoFlags ()
{8}
IRQNoFlags ()
{11}
IRQNoFlags ()
{12}
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
_Y00)
})
Name (HPTC, 0xFED1F404)
OperationRegion (HCNT, SystemMemory, HPTC, 0x04)
Field (HCNT, DWordAcc, NoLock, Preserve)
{
HPTS, 2,
, 5,
HPTE, 1
}
Method (_STA, 0, NotSerialized)
{
If (HPTE)
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
Method (_CRS, 0, NotSerialized)
{
CreateDWordField (CRS, \_SB.PCI0.PCI1.HPET._Y00._BAS, HTBS)
Multiply (HPTS, 0x1000, Local0)
Add (Local0, 0xFED00000, HTBS)
Return (CRS)
}
}
}
Name (_SB.PCI0.SBRG.TMR._STA, Zero)
Device (_SB.PCI0.SBRG.TIMR)
{
Name (_HID, EisaId ("PNP0100"))
Name (_CRS, ResourceTemplate ()
{
IO (Decode16,
0x0040, // Range Minimum
0x0040, // Range Maximum
0x00, // Alignment
0x04, // Length
)
})
}
}