Contribute
Register

IHC7 DSDT AHCI Patch

Status
Not open for further replies.
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).

I changed it from MAPV, 2 to MAPV, 8. Perhaps I'll chasing a wild goose here. I am right that they're the same offset, correct?

Also, with no changes to the DSDT, the default value of MAPV is 0x0. According to the Datasheet, the a value of 00 for MAPV is combined mode. How would I set it to 10? Setting MAPV to 0xA returns

Code:
ACPIDebug: { "PINI_MAPV",0x2, }
but as you say, 10 is outside of a 2bit field.

I thinking I'm banging up against the limits of my knowledge here. I'm not sure what these numbers really represent. How does the 01b, for example, listed in the datasheet translate to the 0x40 value that enables the ACHI controller? Also, what does the bit 7:6 listed next to SATA mode represent? I can't find a legend in the datasheet, so I assume this must be an assumed knowledge thing.

HP4r9P2.png

"When in combined mode, the AHCI memory space is not available." It would seem I need to figure out MAPV first.
 
I changed it from MAPV, 2 to MAPV, 8. Perhaps I'll chasing a wild goose here. I am right that they're the same offset, correct?

They are at the same offset. You may want to also verify that the bits are declared MSB..LSB. I'm not certain of it. Try to read about it in the ACPI spec.

But there is no reason to use their Field entry. What you did before is perfectly valid. That is, it is valid to have multiple Field overlays on the same data structure (in this case PCI config).

Also, with no changes to the DSDT, the default value of MAPV is 0x0. According to the Datasheet, the a value of 00 for MAPV is combined mode. How would I set it to 10? Setting MAPV to 0xA returns

Code:
ACPIDebug: { "PINI_MAPV",0x2, }
but as you say, 10 is outside of a 2bit field.

You got 0x2 after setting it to 0xA because 0xA & 0x3 == 0x2. (1010 & 0011 == 0010).

I thinking I'm banging up against the limits of my knowledge here. I'm not sure what these numbers really represent. How does the 01b, for example, listed in the datasheet translate to the 0x40 value that enables the ACHI controller? Also, what does the bit 7:6 listed next to SATA mode represent? I can't find a legend in the datasheet, so I assume this must be an assumed knowledge thing.

Definitely assumed knowledge about binary numbers/notation.

01b means 01 binary. Two bit number, possibilites are 00, 01, 10, 11 (0, 1, 2, 3).

7:6 means it is in bits 7:6 (the two most significant bits). Bits are generally numbered from 0-n, where n is the number of bits in the data, and where bit 0 is the least significant (2^0) and bit n is the most significant (2^n).

Bit 7 is 2^7, bit 6 is 2^6. The 01b value mentioned would thusly be 0*2^7 | 1*2^6, result 0x40. If you wanted it set to 11b, it would be 1*2^7 | 1*2^6, result 0xC0. Of course 11b is "reserved" so you would not do that. 10b would be 1*2^7 | 0*2^6, or 0x80.

You should probably read up on 'binary' (base 2) and 'hexadecimal' (base 16).
 
They are at the same offset. You may want to also verify that the bits are declared MSB..LSB. I'm not certain of it. Try to read about it in the ACPI spec.

But there is no reason to use their Field entry. What you did before is perfectly valid. That is, it is valid to have multiple Field overlays on the same data structure (in this case PCI config).



You got 0x2 after setting it to 0xA because 0xA & 0x3 == 0x2. (1010 & 0011 == 0010).



Definitely assumed knowledge about binary numbers/notation.

01b means 01 binary. Two bit number, possibilites are 00, 01, 10, 11 (0, 1, 2, 3).

7:6 means it is in bits 7:6 (the two most significant bits). Bits are generally numbered from 0-n, where n is the number of bits in the data, and where bit 0 is the least significant (2^0) and bit n is the most significant (2^n).

Bit 7 is 2^7, bit 6 is 2^6. The 01b value mentioned would thusly be 0*2^7 | 1*2^6, result 0x40. If you wanted it set to 11b, it would be 1*2^7 | 1*2^6, result 0xC0. Of course 11b is "reserved" so you would not do that. 10b would be 1*2^7 | 0*2^6, or 0x80.

You should probably read up on 'binary' (base 2) and 'hexadecimal' (base 16).

Thank you so much for this information; makes much more sense what's going on here now. I'm going to do some reading and I'll post back when I've got some new results.
 
After doing some reading, I have this question:

The Map register memory space contains 8 bits beginning at offset 90. The map value fields lies at bits zero and one of this space, and the sata select field lies at bits six and seven. For AHCI to work, the value in the map value bits must be set to mobile combined, which means that bit 1 must read 0x01, and bit 0 must read 0x00. To enable AHCI, 0x00 must be at bit 7, and 0x40 must be at bit 6.

It looks to me like your Method PINI, the value 0x3F (binary 63) moves to the 6th bit and sets it to 0x40. How would I set bit 1 with the map value of 0x01 I need?

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) 
    }

Would I simply change 0x3f to 0x04?
 
After doing some reading, I have this question:

The Map register memory space contains 8 bits beginning at offset 90. The map value fields lies at bits zero and one of this space, and the sata select field lies at bits six and seven. For AHCI to work, the value in the map value bits must be set to mobile combined, which means that bit 1 must read 0x01, and bit 0 must read 0x00. To enable AHCI, 0x00 must be at bit 7, and 0x40 must be at bit 6.

It looks to me like your Method PINI, the value 0x3F (binary 63) moves to the 6th bit and sets it to 0x40. How would I set the bit 1 with the map value of 0x01 I need?

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) 
    }

Would I simply change 0x3f to 0x04?

To force:
- the bitfield at 1:0 to 10b
- the bitfield at 7:6 to 01b
Code:
 Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        And(\_SB.PCI0.SATA.AHCI, 0x3C, Local0) // mask away 7:6 and 1:0
        Or(Local0, 0x42, Local0) // 7:6=01b, 1:0=10b
        Store (Local0, \_SB.PCI0.SATA.AHCI) 
    }
 
To force:
- the bitfield at 1:0 to 10b
- the bitfield at 7:6 to 01b
Code:
 Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        And(\_SB.PCI0.SATA.AHCI, 0x3C, Local0) // mask away 7:6 and 1:0
        Or(Local0, 0x42, Local0) // 7:6=01b, 1:0=10b
        Store (Local0, \_SB.PCI0.SATA.AHCI) 
    }

Hmm, ACPIDebug confirms that field is set to 0x42, but it boots in legacy ide mode. settings 90.b=42 with setpci doesn't result in a change to the AHCI controller either. Are there any other values I can try?

The numbers for Map Value in the datasheet do not have a b suffix (nor an h for hex). To confirm, they are binary values right?

HP4r9P2.png

Edit: strangely, with 0x42, the finder hard drive icon is a folder...

edit 2: Would it also be possible to set up two fields in the operationregion:

Code:
       OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
                Field (SAHC, ByteAcc, NoLock, Preserve)
                {
                 VMAP, 2,
                 Offset (0x07),
                 AHCI, 2
                }

and then set each field individually?
 
...
The numbers for Map Value in the datasheet do not have a b suffix (nor an h for hex). To confirm, they are binary values right?

Impossible to be anything else than binary. The field is only two bits in size. Probably they just forgot to add the 'b'.

edit 2: Would it also be possible to set up two fields in the operationregion:

Code:
       OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
                Field (SAHC, ByteAcc, NoLock, Preserve)
                {
                 VMAP, 2,
                 Offset (0x07),
                 AHCI, 2
                }

and then set each field individually?

It is possible, but your proposed code is wrong (Offset specifies a byte-offset).

Correct:
Code:
  OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
  Field (SAHC, ByteAcc, NoLock, Preserve)
  {
     VMAP,2,
         ,4,
     AHCI,2
   }

I don't see where the ACPI spec actually states the bit order, so I'm not sure if it is 7...0 or 0..7.

You'll have to experiment to find out.

If it is 7..0, the order would need to change:
Code:
  OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
  Field (SAHC, ByteAcc, NoLock, Preserve)
  {
     AHCI,2
         ,4,
     VMAP,2,
   }
 
Impossible to be anything else than binary. The field is only two bits in size. Probably they just forgot to add the 'b'.



It is possible, but your proposed code is wrong (Offset specifies a byte-offset).

Correct:
Code:
  OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
  Field (SAHC, ByteAcc, NoLock, Preserve)
  {
     VMAP,2,
         ,4,
     AHCI,2
   }

I don't see where the ACPI spec actually states the bit order, so I'm not sure if it is 7...0 or 0..7.

You'll have to experiment to find out.

If it is 7..0, the order would need to change:
Code:
  OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
  Field (SAHC, ByteAcc, NoLock, Preserve)
  {
     AHCI,2
         ,4,
     VMAP,2,
   }

Thank you for that. I'm finding it much easier to wrap my head around this at the binary level.

Okay, so my options for either field are now either 0x0, 0x1, 0x2, or 0x3.

Using ACPIDebug, I've returned the default values for these fields: they are both 0x0

VMAP 0x0 = Non-Combined
AHCI 0x0 = IDE

Per the specs, to enable the AHCI controller, I want a value of binary 01 (0x1) for AHCI, and I want binary 00 (0x0) for VMAP.

Accounting for the uncertainty on if the bits are ordered 0-7 or 7-0, I have two options to try.

0-7:
Code:
AHCI = 0x1; VMAP = 0x0
                OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
                Field (SAHC, ByteAcc, NoLock, Preserve)
                {
                   VMAP, 2, // 0-7 order
                        , 4,
                    AHCI, 2
                }
Result: Boot halts at waiting for root device.
PCIDebug returns:
ACPIDebug: { "PINI_AHCI", 0x1, }
ACPIDebug: { "PINI_VMAP", 0x0, }
ACPIDebug: { "PINI_MAPV", 0x0, } Original "MAPV" field
ACPIDebug: { "DSM_AHCI", 0x1, } _DSM attached to SATA
ACPIDebug: { "DSM_VMAP", 0x0, }
ACPIDebug: { "DSM_MAPV", 0x0, }
(the order these are returned seems to suggest that PINI is being called before the _DSM at the end of SATA, as it should be).

7-0: [this would match the order the data was given in the datasheet, but who knows if that means anything]
Code:
AHCI = 0x1; VMAP = 0x0
                OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
                Field (SAHC, ByteAcc, NoLock, Preserve)
                {
                   AHCI, 2, // 7-0 order
                        , 4,
                    VMAP, 2
                }
Result: Boot halts at waiting for root device.
PCIDebug returns:
ACPIDebug: { "PINI_AHCI", 0x1, }
ACPIDebug: { "PINI_VMAP", 0x0, }
ACPIDebug: { "PINI_MAPV", 0x1, } Original "MAPV" field
ACPIDebug: { "DSM_AHCI", 0x1, } _DSM attached to SATA
ACPIDebug: { "DSM_VMAP", 0x0, }
ACPIDebug: { "DSM_MAPV", 0x1, }

My current method PINI:
Code:
    Method (PINI, 0, NotSerialized) // For PCI0/Wake INI
    {
        Store (0x2, \_SB.PCI0.SATA.VMAP)
        Store (0x1, \_SB.PCI0.SATA.AHCI) 
        \RMDT.P2 ("PINI_AHCI", \_SB.PCI0.SATA.AHCI)
        \RMDT.P2 ("PINI_VMAP", \_SB.PCI0.SATA.VMAP)
        \RMDT.P2 ("PINI_MAPV", \_SB.PCI0.SATA.MAPV)
    }

Given that the Dell MAPV field and my VMAP field match in 0-7 order, that suggests 0-7 is the correct order of the bits.

This seems pretty basic on a binary level, so unless I made an error, to me this suggests that the DSDT code has been fine all along, and OSX is not loading AppleAHCIPort.kext for whatever reason.

Thoughts?

My DSDT set up for 7-0 is attached.
 

Attachments

  • DSDT0-7.dsl.zip
    18.4 KB · Views: 127
You can find out which way it is 7..0 or 0..7 by creating two overlays:

Code:
  OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
  Field (SAHC, ByteAcc, NoLock, Preserve)
  {
     VMAP,2,
         ,4,
     AHCI,2
   }
  OperationRegion (SAH1, PCI_Config, 0x90, One) // AHCI
  Field (SAH1, ByteAcc, NoLock, Preserve)
  {
     AHCX,8
   }

Now you can manipulate as bitfields, but then still look at the entire byte:
Code:
Store(AHCX, Local0) // save it
Store(1, VMAP)
Store(0, AHCI)
\rmdt.p2("AHCX is", AHCX)
Store(Local0, AHCX) // restore it

Assuming the reserved bits are zero, if it prints 0x40, then you know it is 7..0. If it prints 0x01, then it must be 0..7.

Also, usually the device-id is different for a device in AHCI vs. IDE mode. This is how different drivers attach (different IOKitPersonality matches via IOKit matching).

In your case, you're changing the mode of the device after the PCI device-ids have already been captured. So you'll need some sort of device-id injection to cause the correct driver to attach and maybe even FakePCIID to fake the correct PCI ids.
 
You can find out which way it is 7..0 or 0..7 by creating two overlays:

Code:
  OperationRegion (SAHC, PCI_Config, 0x90, One) // AHCI
  Field (SAHC, ByteAcc, NoLock, Preserve)
  {
     VMAP,2,
         ,4,
     AHCI,2
   }
  OperationRegion (SAH1, PCI_Config, 0x90, One) // AHCI
  Field (SAH1, ByteAcc, NoLock, Preserve)
  {
     AHCX,8
   }

Now you can manipulate as bitfields, but then still look at the entire byte:
Code:
Store(AHCX, Local0) // save it
Store(1, VMAP)
Store(0, AHCI)
\rmdt.p2("AHCX is", AHCX)
Store(Local0, AHCX) // restore it

Assuming the reserved bits are zero, if it prints 0x40, then you know it is 7..0. If it prints 0x01, then it must be 0..7.

Great Idea. I implemented this and AHCX returns 0x40 when in 0-7 order.

Also, usually the device-id is different for a device in AHCI vs. IDE mode. This is how different drivers attach (different IOKitPersonality matches via IOKit matching).

In your case, you're changing the mode of the device after the PCI device-ids have already been captured. So you'll need some sort of device-id injection to cause the correct driver to attach and maybe even FakePCIID to fake the correct PCI ids.

Also a great idea, however I attempted to add the device ID for my IDE controller to AppleAHCIPort.kext and the problem still persists. I also attempted to use _DSM injection to no avail. I searched for C5 27 in the binary and got no matches, (though there was a single match for 86 80).

I might be taking a shot in the dark, but I have a hypothesis as to what's going on.

In order to get into the OS so I can run tools to try and further diagnose the problem, I took the SATA controller out of the equation by installing Snow Leopard to a external USB drive. On 10.6.0 I got an AppleAHCIPort.kext kernel panic (with no edits to the Info.plist, and no _DSM, so it's likely reading the device-id correctly if it's attempting to load and paniced). After updating to 10.6.8 I can boot into the USB OSX install with the AHCI controller enabled, but the drive doesn't attach. There is nothing in the console about AppleAHCIPort.kext on boot. An IOReg is attached.

lspci is as it should be:
Code:
00:1f.2 SATA controller [0106]: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA AHCI Controller [8086:27c5] (rev 02)

I think we can lay this one to bed: we are correctly enabling the AHCI controller with the DSDT patch. The problem likely lies elsewhere.

While I was comparing my IOReg output to that of a MacBookPro2,1 with the same chipset, I noticed that it's sata ports were labeled PRT0, and PRT2 (as it should be as P0 is primary in non-combined, P2 is slave). Mine is labeled PRID ("PortIDE" perhaps?).

Could it be that the problem here is simply that I don't have any AHCI SATA ports defined in the DSDT, or am I incorrect in my thinking and the SATA IDE Controller and AHCI controller do not share the same DSDT port definitions? If it's the former, it would seem Dell wouldn't bother to add them if they had no intentions of giving an AHCI option. An IOReg with the controller enabled, and the two vanilla SSDTs where SATA related items are located are attached.

Thanks again; you've been a huge help thus far. Thoughts?

Here's the relevant parts of the datasheet. They would appear to have different locations.

Edit: hers a picture of the 10.6.0 panic.

 

Attachments

  • Archive.zip
    331.7 KB · Views: 133
Status
Not open for further replies.
Back
Top