Contribute
Register

IHC7 DSDT AHCI Patch

Status
Not open for further replies.
Joined
Oct 22, 2013
Messages
197
Motherboard
hm77
CPU
4790k
Graphics
hd4000
Though my chipset supports it, Dell didn't provide a BIOS option for AHCI; I'm stuck on legacy IDE.
Code:
00:1f.2 IDE interface [0101]: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA IDE Controller [8086:27c4] (rev 02)
I've been doing research, and the Intel Datasheet states that my chipset fully supports AHCI. In that case, it seems possible to enable AHCI with a DSDT patch.

To confirm support, if I issue this command in OSX's Terminal, I can switch to the AHCI controller, but the OS quickly locks up the first time anything tries to read from the disk (obviously).
Code:
$ setpci -s 00:1f.2 90.b=40
$ lspci -nn
$ 00:1f.2 SATA controller [0106]: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA AHCI Controller [8086:27c5] (rev 02)

so it should be possible to get this machine to boot in AHCI mode.

On page 509 of the IHC7 datasheet, section 12.1.33, one can find the necessary information to enable AHCI:
HP4r9P2.png


To enable this in the DSDT, I created an OperationRegion under device SATA with an offset of 0x90 with a size of 0x08, that contains an 8bit field named AHCI.
Code:
 Device (SATA)
            {
                Name (_ADR, 0x001F0002)  // _ADR: Address[B]
                OperationRegion (SAHC, PCI_Config, 0x90, 0x08) // AHCI
                Field (SAHC, ByteAcc, NoLock, Preserve)
                {
                    AHCI, 8
                }[/B]
                
                OperationRegion (SACS, PCI_Config, 0x40, 0xC0)
 <<< REST OF DEVICE SATA >>>

To set this field, I created a method called PINI a the root of the DSDT:
Code:
    Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        Store (0x40, \_SB.PCI0.SATA.AHCI) // Force SATA in 4-Port AHCI mode
    }

To execute this method on boot, I created a method _INI for device PCI
Code:
            Method (_INI, 0, NotSerialized)
            {
                PINI ()
            }

To execute this method on wake, I added this to _WAK:
Code:
    Method (_WAK, 1, NotSerialized)  // _WAK: Wake
    {
        [B]PINI ()[/B]
        P8XH (Zero, 0xAB)
 <<< REST OF method _WAK >>>

With these changes in place, booting without the cache, I get a "still waiting for root device" error on boot. It would seem it's not loading the AppleAHCI driver.

What am I doing wrong?

From the Datasheet, it says that the controller must have map value set to non-combined mode. Given that it came from the factory in combined, I'd likely have to set this value too. How would i go about doing that?

Attached is my DSDT.
 

Attachments

  • ahci.dsl.zip
    18.1 KB · Views: 239
Though my chipset supports it, Dell didn't provide a BIOS option for AHCI; I'm stuck on legacy IDE.
Code:
00:1f.2 IDE interface [0101]: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA IDE Controller [8086:27c4] (rev 02)
I've been doing research, and the Intel Datasheet states that my chipset fully supports AHCI. In that case, it seems possible to enable AHCI with a DSDT patch.

To confirm support, if I issue this command in OSX's Terminal, I can switch to the AHCI controller, but the OS quickly locks up the first time anything tries to read from the disk (obviously).
Code:
$ setpci -s 00:1f.2 90.b=40
$ lspci
$ 00:1f.2 SATA controller: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA AHCI Controller (rev 02)

so it should be possible to get this machine to boot in AHCI mode.

On page 509 of the IHC7 datasheet, section 12.1.33, one can find the necessary information to enable AHCI:
HP4r9P2.png


To enable this in the DSDT, I created an OperationRegion under device SATA with an offset of 0x90 with a size of 0x08, that contains an 8bit field named AHCI.
Code:
 Device (SATA)
            {
                Name (_ADR, 0x001F0002)  // _ADR: Address[B]
                OperationRegion (SAHC, PCI_Config, 0x90, 0x08) // AHCI
                Field (SAHC, ByteAcc, NoLock, Preserve)
                {
                    AHCI, 8
                }[/B]
                
                OperationRegion (SACS, PCI_Config, 0x40, 0xC0)
 <<< REST OF DEVICE SATA >>>

To set this field, I created a method called PINI a the root of the DSDT:
Code:
    Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        Store (0x40, \_SB.PCI0.SATA.AHCI) // Force SATA in 4-Port AHCI mode
    }

To execute this method on boot, I created a method _INI for device PCI
Code:
            Method (_INI, 0, NotSerialized)
            {
                PINI ()
            }

To execute this method on wake, I added this to _WAK:
Code:
    Method (_WAK, 1, NotSerialized)  // _WAK: Wake
    {
        [B]PINI ()[/B]
        P8XH (Zero, 0xAB)
 <<< REST OF method _WAK >>>

With these changes in place, booting without the cache, I get a "still waiting for root device" error on boot. It would seem it's not loading the AppleAHCI driver.

What am I doing wrong?

From the Datasheet, it says that the controller must have map value set to combined mode. Given that it came from the factory in non-combined, I'd likely have to set this value too. How would i go about doing that?

Attached is my DSDT.

Did you check in the Info.plist for the ACHI driver to see if it lists your device-id?

If it is not there, you need to patch it or use an injector kext.

Note: The length of the OperationRegion is in bytes, not bits (the length of fields are specified in bits).

Note 2: You may not need the PINI/_WAK stuff if the device mode is retained across sleep (likely).
 
Did you check in the Info.plist for the ACHI driver to see if it lists your device-id?

If it is not there, you need to patch it or use an injector kext.

Caught me before my edit. I did; my ACHI SATA device id is 8086:27c5, the same as the MacbookPro2,1 which also uses the ICH7 chipset, and that value can be found in AppleAHCI.kext's Info.plist.
 
Note: The length of the OperationRegion is in bytes, not bits (the length of fields are specified in bits).

Good catch; I changed the size to One. Still doesn't find root device, however.

Code:
OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI

Code:
Note 2: You may not need the PINI/_WAK stuff if the device mode is retained across sleep (likely).

Thanks for the info, I'll test that once I get it booting.

Any other ideas?
 
Good catch; I changed the size to One. Still doesn't find root device, however.

Code:
OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI

Code:
Note 2: You may not need the PINI/_WAK stuff if the device mode is retained across sleep (likely).

Thanks for the info, I'll test that once I get it booting.

Any other ideas?

Try changing just the bits you need to change...

Code:
    Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        And(\_SB.PCI0.SATA.AHCI, 0x3F, Local0)
        Or(Local0, 0x40, Local0)
        Store (Local0, \_SB.PCI0.SATA.AHCI) 
    }

You can also use ACPIDebug to test whether your code is running.
 
New information: The command setpci -s 00:1f.2 90.b=2 enables the legacy IDE SATA controller. If I swap out 0x40 for 0x02 in my original method PINI thusly:
Code:
Store (0x02, \_SB.PCI0.SATA.AHCI)
The machine boots in legacyIDE mode.

Try changing just the bits you need to change...

Code:
    Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        And(\_SB.PCI0.SATA.AHCI, 0x3F, Local0)
        Or(Local0, 0x40, Local0)
        Store (Local0, \_SB.PCI0.SATA.AHCI) 
    }
This code doesn't work with 0x40. With 0x02 it boots, so it would seem either method would work. I like your way better.

This would seem to suggest the problem is on OSX's end, and the DSDT code is working as intended.

You can also use ACPIDebug to test whether your code is running.

Good idea; I've already got a 32bit ACPIDebug sitting around. I'll use it to confirm that PCI0._INI and method PINI are being run, which should confirm what I suspect to be true from the above test.

If the DSDT is fine, what could be causing OSX not to load the driver even through I have the same device id as a real MacBookPro2,1?

There is also the issue with the map value I mentioned in the OP. There is a field
Code:
                    Offset (0x50), 
                    MAPV,   2
Under the original device SATA operationregion. It isn't referenced anywhere else in the code. Is there a way to get the DSDT to echo to the console the contents of the map value (perhaps MAPV) field?
 
Yup, I installed ACPIDebug and added it to PCI0.INI and PINI and got this in the console:

Code:
5/31/15 6:42:16 PM    kernel    ACPIDebug: Version 0.1.2 starting
5/31/15 6:42:16 PM    kernel    ACPIDebug: "PCI0INI enter"
5/31/15 6:42:16 PM    kernel    ACPIDebug: "PINI enter"
5/31/15 6:42:16 PM    kernel    ACPIDebug: "PINI exit"
5/31/15 6:42:16 PM    kernel    ACPIDebug: "PCI0INI exit"

The code is running.
 
...
There is also the issue with the map value I mentioned in the OP. There is a field
Code:
                    Offset (0x50), 
                    MAPV,   2
Under the original device SATA operationregion. It isn't referenced anywhere else in the code. Is there a way to get the DSDT to echo to the console the contents of the map value (perhaps MAPV) field?

You can dump anything you want with ACPIDebug...
 
You can dump anything you want with ACPIDebug...

Here's what I've learned using ACPIDebug to dump those fields.

This is my vanilla device SATA
Code:
            Device (SATA)
            {
                Name (_ADR, 0x001F0002)  // _ADR: Address
                OperationRegion (SACS, PCI_Config, [B]0x40[/B], 0xC0)
                Field (SACS, DWordAcc, NoLock, Preserve)
                {
                    PRIT,   16, 
                    SECT,   16, 
                    PSIT,   4, 
                    SSIT,   4, 
                    Offset (0x08), 
                    SYNC,   4, 
                    Offset (0x0A), 
                    SDT0,   2, 
                        ,   2, 
                    SDT1,   2, 
                    Offset (0x0B), 
                    SDT2,   2, 
                        ,   2, 
                    SDT3,   2, 
                    Offset (0x14), 
                    ICR0,   4, 
                    ICR1,   4, 
                    ICR2,   4, 
                    ICR3,   4, 
                    ICR4,   4, 
                    ICR5,   4, 
                    [B]Offset (0x50), 
                    MAPV,   2[/B]
                }
            }
The start of this operationregion is offset 0x40, so if I understand this correctly, MAPV, at 0x50 is the same offset 0x90 as the the AHCI field I've been working with (0x40+0x50=0x90).

To confirm this, I set AHCI to 0x40 and, after changing MAPV into an 8byte field, and using ACPIDebug to return the value found at MAPV, it was 0x40.

Given this, I deleted the operationregion at 0x90 I added, and am now trying to work with MAPV. This is my current method PINI. As before, it boots with 0x02, but not with 0x40.
Code:
into definitionblock code_regex . insert begin
    Method (PINI, 0, NotSerialized) // Sets SATA mode to AHCI
    {
        And(\_SB.PCI0.SATA.MAPV, 0x3F, Local0)
        Or(Local0, 0x40, Local0)
        Store (Local0, \_SB.PCI0.SATA.AHCI)
        \RMDT.P2 ("PINI_MAPV", \_SB.PCI0.SATA.MAPV)
    }
end;

Can you see anything wrong with this technique? Thanks for creating ACPIDebug; it's an amazingly handy tool for this.
 
Here's what I've learned using ACPIDebug to dump those fields.

This is my vanilla device SATA
Code:
            Device (SATA)
            {
                Name (_ADR, 0x001F0002)  // _ADR: Address
                OperationRegion (SACS, PCI_Config, [B]0x40[/B], 0xC0)
                Field (SACS, DWordAcc, NoLock, Preserve)
                {
                    PRIT,   16, 
                    SECT,   16, 
                    PSIT,   4, 
                    SSIT,   4, 
                    Offset (0x08), 
                    SYNC,   4, 
                    Offset (0x0A), 
                    SDT0,   2, 
                        ,   2, 
                    SDT1,   2, 
                    Offset (0x0B), 
                    SDT2,   2, 
                        ,   2, 
                    SDT3,   2, 
                    Offset (0x14), 
                    ICR0,   4, 
                    ICR1,   4, 
                    ICR2,   4, 
                    ICR3,   4, 
                    ICR4,   4, 
                    ICR5,   4, 
                    [B]Offset (0x50), 
                    MAPV,   2[/B]
                }
            }
The start of this operationregion is offset 0x40, so if I understand this correctly, MAPV, at 0x50 is the same offset 0x90 as the the AHCI field I've been working with (0x40+0x50=0x90).

To confirm this, I set AHCI to 0x40 and, after changing MAPV into an 8byte field, and using ACPIDebug to return the value found at MAPV, it was 0x40.

It is impossible to set MAPV to 0x40. It is only two bits. Largest number for two bits is (2^2)-1, which is 3.

The idea would be to set MAPV to 1. (0x01, or binary 01).

But still, it is the same as what was proposed before (where the necessary And/Or was done manually).
 
Status
Not open for further replies.
Back
Top