- Joined
- Aug 17, 2017
- Messages
- 307
- Motherboard
- ASUS Prime X299 Edition 30
- CPU
- i9-10980XE
- Graphics
- RX 5700 XT
- Mac
- Mobile Phone
Ok, here we are!
After a long search I found something interesting and... a possible way to have Thunderbolt hotswap working!
I start this thread with the hope that finally we can create a definitive guide (or almost) to enable the thunderbolt hot swap.
If it works, it would be a turning point for the whole community!
Originally post by maleorderbride
Unfortunately I do not understand much, I have never put my hand on an SSDT... but if someone is practical it could help us create a generic guide for everyone.
Any idea?
After a long search I found something interesting and... a possible way to have Thunderbolt hotswap working!
I start this thread with the hope that finally we can create a definitive guide (or almost) to enable the thunderbolt hot swap.
If it works, it would be a turning point for the whole community!
Originally post by maleorderbride
This is a mini-guide to get Thunderbolt hotswap working. My SSDT is for an ASRock TB3 (JHL6540) card in my X299 motherboard, but I know this also works with the Gigabyte X99 Designare's built-in TB3 port.
Based on the TheRacerMaster's work, and remote.syst3m's idea to change the value of "PCIHotplugCapable", I have TB3 hotswap working. Thunderbolt does not show as loaded in System Profiler, and this is undoubtedly a bit of a hack, but it seems to work and it is quite easy to implement.
TheRacer Master's github work seems to be based on importing MacBookPro14,1 ACPI information. You can find some raw Darwin Dumps here from him that contain DSDTs, SSDTs, and IOreg.
Below is the seemingly relevant bit, pulled from TheRacerMaster's github, with only the "PCIHotplugCapable" value changed to enabled and a few values modified to fit my computer.
Code:Device (DSB0) { Name (_ADR, Zero) // _ADR: Address Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method { If (LNot (Arg2)) { Return (Buffer (One) { 0x03 }) } Return (Package (0x02) { "PCIHotplugCapable", One }) }
I implemented this as an SSDT, but perhaps one could simply inject the single property via Clover arbitrary, or just the DSB0 device with that one property.
1. What you need:
IOregistryExplorer (or IOJones)
MaciASL (use Rehabman's patchmatic)
Thunderbolt working (just without hotswap)
2. Identify the TB device address
2.1 Open IOreg and find your thunderbolt device(s) by typing in "thunderbolt" in the search bar.
2.2. Take note of the address (PCI0.RP05 for me).
2.3. Now clear the thunderbolt search and switch to IOACPIPlane view on the top right of IOreg. Find that same address. You should see a few other entires under it, and make note of whatever does not begin with H (for X99), and any values for X299. In this case, mine are PXSX and SLT5. We are going to prevent these from loading by setting their STA value to Zero so that our devices load instead.
3. Modify stock SSDT
3.1 Download the attached base SSDT and replace any instances of PCI0.RP05 with your actual address. If you have multiple thunderbolt controllers then copy and modify accordingly.
3.2. Replace PXSX and SLT5 with your value(s) from IOACPIPlane view. You might only have one value, in which case you can delete the extra line from the stock SSDT.
That should be it! Reboot and open IOreg again. Look to see if you now have PCIHotplugCapable set to "True" on the right-hand side. If so, then it should be working.
4. Inject USB ports (not required for hotswap)
I also hardcoded the two USB 3.1 ports on my card to clear up some complaints during verbose startup. This was pulled from one of PikerAlpha's blog posts.
I don't think it matters which device you inject this into (DSB2,3,4), but I chose DSB2 based upon the address on my particular card (0x0002000) locatable in IOreg. If I had had 0x0003000 then I would have done DSB3, etc.
If you only have one TB3 port, then you only need HS01 and SSP1.
If you already have an XHC2 device, then name it XHC3, 4, or whatever is appropriate.
Code:Device (DSB2) { Name (_ADR, 0x00020000) // _ADR: Address Device (XHC2) { Name (_ADR, Zero) // _ADR: Address Device (RHUB) { Name (_ADR, Zero) // _ADR: Address Device (SSP1) { Name (_ADR, One) // _ADR: Address Name (_UPC, Package (0x04) // _UPC: USB Port Capabilities { 0xFF, 0x09, Zero, Zero }) Name (_PLD, Package (0x01) // _PLD: Physical Location of Device { Buffer (0x10) { /* 0000 */ 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0008 */ 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }) Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method { If (LEqual (Arg2, Zero)) { Return (Buffer (One) { 0x03 }) } Return (Package (0x02) { "UsbCPortNumber", One }) } } Device (SSP2) { Name (_ADR, 0x02) // _ADR: Address Name (_UPC, Package (0x04) // _UPC: USB Port Capabilities { 0xFF, 0x09, Zero, Zero }) Name (_PLD, Package (0x01) // _PLD: Physical Location of Device { Buffer (0x10) { /* 0000 */ 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0008 */ 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }) Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method { If (LEqual (Arg2, Zero)) { Return (Buffer (One) { 0x03 }) } Return (Package (0x02) { "UsbCPortNumber", 0x02 }) } } Device (HS01) { Name (_ADR, 0x03) // _ADR: Address Name (_UPC, Package (0x04) // _UPC: USB Port Capabilities { 0xFF, 0x09, Zero, Zero }) Name (_PLD, Package (0x01) // _PLD: Physical Location of Device { Buffer (0x10) { /* 0000 */ 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0008 */ 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }) } Device (HS02) { Name (_ADR, 0x04) // _ADR: Address Name (_UPC, Package (0x04) // _UPC: USB Port Capabilities { 0xFF, 0x09, Zero, Zero }) Name (_PLD, Package (0x01) // _PLD: Physical Location of Device { Buffer (0x10) { /* 0000 */ 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0008 */ 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }) } } } }
Unfortunately I do not understand much, I have never put my hand on an SSDT... but if someone is practical it could help us create a generic guide for everyone.
Any idea?