ProjectOSX

Welcome Guest!

Returning User? Login here.

Want membership privileges? Register here.

 
Start a new topic Add Reply
> Fixing Bad Pci Io & Mem, Got an Acer? Fix now available
darkuttek
post May 4 2011, 10:14 PM
Post #1
Hello boys and girls,

Got an Acer? Your built-in ethernet isn't working? No IO, MEM and MEM PF given by the bios for your PCI bridges? Been frustrated, lost all your hope?

Time to regain it. For the fix you have been waiting for ages is finally here.

No, it won't be easy and it isn't done by moving a precompiled kext to S/L/E. And it is somewhat dirty hack. You won't be able to just copy it from one Hackintosh to another. But it should be stable (first got things rolling with the changes done by Chun-nan. That was however way too unstable and didn't really fix my Express Card slot and Firewire card, so I decided to make things from scratch).

So first my testimony: I'm running a Acer Aspire 7730G. Before this I didn't have my built-in network adapter working nor did my Firewire Express Card work either. Now those are fixed.

Things you'll be needing for this:
- Latest free Xcode
- Fixed DSDT
- Linux
- Fearlessness
- Darkuttek's IOPCIFamily-115 modified source code package

Let's start with the first one. Head over to http://developer.apple.com/. Sign up for the free Apple developer program and download Xcode. Install it.

Okay, that's now done. Next, DSDT. I won't be going over the process of obtaining one here, there are good guides everywhere on the internet. This step is important, as the less you got things broken, less hanging etc. So make sure you do these modifications to your DSDT:
HPET IRQ: http://www.projectosx.com/forum/index.php?showtopic=564
UHCI/EHCI USB fix Guide I followed: http://webcache.googleusercontent.com/sear...=www.google.com

Next, boot up Linux and do lspci -v and write it all down. Then boot osx and run lspci -v there also, writing everything down. You can get it here.

Now then, the tricky part. Find in OSX the PCI bridges which aren't getting good addresses. Make note of their bus, secondary bus and sub busnumbers (xx:xx:xx). How many are there of those? What would their correct addresses be -- find this out by comparing to Linux lspci -v.

Now then. You have downloaded the sources? Okay, open the project in Xcode. Go to file IOPCIConfigurator.cpp and there find void CLASS::pciBridgeProbeRanges. There find the code below:
CODE
    end = configRead32(bridge->space, kPCI2PCIMemoryRange);
    if (end)
    {
    //    IOLog("  Bridge Bus %d subBus %d MEM non modified END %lu\n",
    //          bridge->secBusNum, bridge->subBusNum, end);
        start = (end & 0xfff0) << 16;
        end  |= 0x000fffff;
    //    IOLog("  Bridge Bus %d subBus %d MEM RANGE START %lu END %lu\n",
    //          bridge->secBusNum, bridge->subBusNum, start, end);
        
        if (end > start)
        {
            range = &bridge->ranges[kIOPCIRangeBridgeMemory];
            range->start = start;
            range->size  = end - start + 1;
            range->alignment = kPCIBridgeMemoryAlignment;
            range->type = kIOPCIResourceTypeMemory;
        }
        
    }
    else
        {
            if (!purkka && bridge->secBusNum == 2 && bridge->subBusNum == 4)
            {
                range = &bridge->ranges[kIOPCIRangeBridgeMemory];
                range->start = 0xc0000000; //3221225472;
                range->size = 0xc01fffff - 0xc0000000 + 1; //2097151;
                range->alignment = kPCIBridgeMemoryAlignment;
                range->type = kIOPCIResourceTypeMemory;
            //    IOLog("Uudet MEM tiedot annettu!\n");
                purkka = true;
            }
            if (!purkka && bridge->secBusNum == 6 && bridge->subBusNum == 6)
            {
                range = &bridge->ranges[kIOPCIRangeBridgeMemory];
                range->start = 0xc0400000;
                range->size = 0xc05fffff - 0xc0400000 + 1;
                range->alignment = kPCIBridgeMemoryAlignment;
                range->type = kIOPCIResourceTypeMemory;
            //    IOLog("Uudet MEM tiedot annettu!\n");
                purkka = true;
            }
            if (!purkka && bridge->secBusNum == 7 && bridge->subBusNum == 7)
            {
                range = &bridge->ranges[kIOPCIRangeBridgeMemory];
                range->start = 0xc0800000;
                range->size = 0xc09fffff - 0xc0800000 + 1;
                range->alignment = kPCIBridgeMemoryAlignment;
                range->type = kIOPCIResourceTypeMemory;
            //    IOLog("Uudet MEM tiedot annettu!\n");
                purkka = true;
            }
            if (!purkka && bridge->secBusNum == 9 && bridge->subBusNum == 9)
            {
                range = &bridge->ranges[kIOPCIRangeBridgeMemory];
                range->start = 0xc0c00000;
                range->size = 0xc0dfffff - 0xc0c00000 + 1;
                range->alignment = kPCIBridgeMemoryAlignment;
                range->type = kIOPCIResourceTypeMemory;
            //    IOLog("Uudet MEM tiedot annettu!\n");
                purkka = true;
            }

        }


Now then. This is the code where we set up the PCI bridges right MEMORY addresses. Things you should be changing here are these:
CODE
            if (!purkka && bridge->secBusNum == [b]2[/b] && bridge->subBusNum == [b]4[/b])
            {
                range = &bridge->ranges[kIOPCIRangeBridgeMemory];
                range->start = [b]0xc0000000[/b]; //3221225472;
                range->size = [b]0xc01fffff - 0xc0000000[/b] + 1; //2097151;
                range->alignment = kPCIBridgeMemoryAlignment;
                range->type = kIOPCIResourceTypeMemory;
            //    IOLog("Uudet MEM tiedot annettu!\n");
                purkka = true;
            }


Change the 2 and 4 to those of the first pci bridge which isn't getting good address. The one in the code is set for 00:02:04 (linux numbering, osx gives them in format Bus: primary=00, secondary=02, subordinate=04
Then look up in the linux lspci the Memory behind bridge: c0000000-c01fffff and change there, so that the numbers begin with 0x. Then repeat this for all PCI bridges which are getting wrong addresses, delete extra. Look how it is in the code atm.

Next part:
CODE
end = configRead32(bridge->space, kPCI2PCIPrefetchMemoryRange);
    // IOLog("  Bridge Bus %d subBus %d PREF MEM non modified END %lu\n",
    //      bridge->secBusNum, bridge->subBusNum, end);
    if (end)
    {
        start = (end & 0xfff0) << 16;
        end  |= 0x000fffff;
        //      IOLog("  Bridge Bus %d subBus %d MEM RANGE START %lu END %lu\n",
        //            bridge->secBusNum, bridge->subBusNum, start, end);

        if (!purkka && bridge->secBusNum == 2 && bridge->subBusNum == 4)
        {
            range = &bridge->ranges[kIOPCIRangeBridgePFMemory];
            range->start = 0xc0200000;
            range->size = 0xc03fffff - 0xc0200000 + 1;
            range->alignment = kPCIBridgeMemoryAlignment;
            range->type = kIOPCIResourceTypePrefetchMemory;
        //    IOLog("Uudet PREF MEM tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && bridge->secBusNum == 6 && bridge->subBusNum == 6)
        {
            range = &bridge->ranges[kIOPCIRangeBridgePFMemory];
            range->start = 0xc0600000;
            range->size = 0xc07fffff - 0xc0600000 + 1;
            range->alignment = kPCIBridgeMemoryAlignment;
            range->type = kIOPCIResourceTypePrefetchMemory;
        //    IOLog("Uudet PREF MEM tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && bridge->secBusNum == 7 && bridge->subBusNum == 7)
        {
            range = &bridge->ranges[kIOPCIRangeBridgePFMemory];
            range->start = 0xc0a00000;
            range->size = 0xc0bfffff - 0xc0a00000 + 1;
            range->alignment = kPCIBridgeMemoryAlignment;
            range->type = kIOPCIResourceTypePrefetchMemory;
        //    IOLog("Uudet PREF MEM tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && bridge->secBusNum == 9 && bridge->subBusNum == 9)
        {
            range = &bridge->ranges[kIOPCIRangeBridgePFMemory];
            range->start = 0xc0e00000;
            range->size = 0xc0ffffff - 0xc0e00000 + 1;
            range->alignment = kPCIBridgeMemoryAlignment;
            range->type = kIOPCIResourceTypePrefetchMemory;
        //    IOLog("Uudet PREF MEM tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && end > start)
        {
            range = &bridge->ranges[kIOPCIRangeBridgePFMemory];
            range->start = start;
            range->size  = end - start + 1;
            range->alignment = kPCIBridgeMemoryAlignment;
            range->type = kIOPCIResourceTypePrefetchMemory;
        }
    }


Do you guess the drill? It is now the same as above, but this time we'll be taking the Prefetchable memory behind bridge: 00000000c0200000-00000000c03fffff. Start with the first character. Repeat.

Then the third part:
CODE
end = configRead32(bridge->space, kPCI2PCIIORange);
    // IOLog("  Bridge Bus %d subBus %d IO non modified END %lu\n",
    //      bridge->secBusNum, bridge->subBusNum, end);
    if (end && ((end & (0x0e0e)) == 0))
    {
        // I/O Base and Limit register at dword 7 (0x1c).
        // If bridge does not implement an I/O address range, then both
        // the I/O Base and I/O Limit registers must be implemented as
        // read-only registers that return zero when read. The bottom
        // and the top of the I/O address range will always be aligned
        // to a 4KB boundary.
        //
        //  I/O Limit  |  I/O  Base
        // 7...4 3...0 | 7...4 3...0
        //  ^     ^       ^     ^
        //  |     |       |     |
        //  |     |       |     +- 0 for 16bit decode, 1 for 32-bit decode
        //  |     |       |
        //  |     |       +-  Upper hex digit of 16-bit or 32-bit I/O range
        //  |     |           start address. Read-only field.
        //  |     |
        //  |     +- 0 for 16bit decode, 1 for 32-bit decode
        //  |
        //  +- Upper hex digit of 16-bit or 32-bit I/O range end address.
        //     Read-write field.
        
        start = (end & 0xf0) << 8;
        end   = (end & 0xffff) | 0xfff;
        //IOLog("  Bridge Bus %d subBus %d IO RANGE START %lu END %lu\n",
        //      bridge->secBusNum, bridge->subBusNum, start, end);

        // Limit may be less than the base, when there are no I/O addresses
        // on the secondary side of the bridge. Or when BIOS has failed to
        // assign I/O resources to devices behind the bridge.
        if (!purkka && bridge->secBusNum == 2 && bridge->subBusNum == 4)
        {
            range = &bridge->ranges[kIOPCIRangeBridgeIO];
            range->start = 0x3000;
            range->size = 0x3fff - 0x3000 + 1;
            range->alignment = kPCIBridgeIOAlignment;
            range->type = kIOPCIResourceTypeIO;
            bridge->deviceState = kPCIDeviceStateResourceAssigned;
            // IOLog("Uudet IO tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && bridge->secBusNum == 6 && bridge->subBusNum == 6)
        {
            range = &bridge->ranges[kIOPCIRangeBridgeIO];
            range->start = 0x4000;
            range->size = 0x4fff - 0x4000 + 1;
            range->alignment = kPCIBridgeIOAlignment;
            range->type = kIOPCIResourceTypeIO;
            bridge->deviceState = kPCIDeviceStateResourceAssigned;
            // IOLog("Uudet IO tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && bridge->secBusNum == 7 && bridge->subBusNum == 7)
        {
            range = &bridge->ranges[kIOPCIRangeBridgeIO];
            range->start = 0x5000;
            range->size = 0x5fff - 0x5000 + 1;
            range->alignment = kPCIBridgeIOAlignment;
            range->type = kIOPCIResourceTypeIO;
            bridge->deviceState = kPCIDeviceStateResourceAssigned;
            // IOLog("Uudet IO tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && bridge->secBusNum == 9 && bridge->subBusNum == 9)
        {
            range = &bridge->ranges[kIOPCIRangeBridgeIO];
            range->start = 0x6000;
            range->size = 0x6fff - 0x6000 + 1;
            range->alignment = kPCIBridgeIOAlignment;
            range->type = kIOPCIResourceTypeIO;
            bridge->deviceState = kPCIDeviceStateResourceAssigned;
            // IOLog("Uudet IO tiedot annettu!\n");
            purkka = true;
        }
        if (!purkka && end > start)
        {
            range = &bridge->ranges[kIOPCIRangeBridgeIO];
            range->start = start;
            range->size  = end - start + 1;
            range->alignment = kPCIBridgeIOAlignment;
            range->type = kIOPCIResourceTypeIO;
        }

    }


This time I/O behind bridge: 00003000-00003fff.

Please note that this hack assumes that the first PCI bridge under which the Graphics adapter is located is working.

Now, in order to have the Express Card working, I had to take some extra steps. I'm having a firewire card, which is composed on hardware level of a pci bridge and the firewire adapter. The adapter had some bad addresses set, because of which it was understood by the driver to have correctly set ranges. In order to force the reallocation of memory for it, I made one dirty hack more. You'll probably want to remove it in case you aren't having the same kind of problem as me.

Find the following code:
CODE
    FOREACH_CHILD(bridge, child)
    {
        if ((child->deviceState == kPCIDeviceStateResourceWait) || (bridge->secBusNum == 3 && bridge->subBusNum == 3))
        {
            allocNeeded = true;
            break;
        }
    }


Remove the part || (bridge->secBusNum == 3 && bridge->subBusNum == 3) or alternatively you can change the numbers to correspond to your case. Please note, that this doesn't check for the primary bus number, so watch out for conflicts!

After you have done the changes, compile and copy the kext from build/Development to your /S/L/E and fix the rights. Then boot your computer and hope for the best.


Well, that's it. Hopefully didn't forget any step. You can contact me here if you get problems. However, I'm not promising anything -- especially, if you aren't running Acer Aspire 7730 or even Acer. But you can try, of course.
Slice
post May 5 2011, 06:10 AM
Post #2
It's a pity this is not universal solution.
Well, it may be useful for someone.
Пожалуйста, прочитайте ЧаВо!
i3-2120 GA-H61M-S1, Radeon HD6670, ALC887(VoodooHDA 2.8.4), OS⌘10.9.1, OS⌘ 10.7.5 Clover FakeSMC_plugins_3.3.1 Realtek LAN v3.1.2
darkuttek
post May 5 2011, 08:44 AM
Post #3
Yeah, that's true. I wasn't really up to that, unfortunately.

However, after doing this I really know how the IOPCIFamily works normally -- and why it doesn't seem to do anything normally. The thing is, there are functions already in place for fixing bad IO ranges. They just aren't run except on PCI bridges which have hotplug As the root bridge doesn't have it, those functions aren't run on it. Chun-nan's modifications made those to be run always. The problem was however that the code wasn't that good in finding out the needed ranges. That resulted in overlapping, which in turn brought in the hangs during the boot process.

My modifications set manually the ranges for pci bridges on the second level counting downwards from the root. I have then modified it so that for devices under those bridges the code looking for child nodes and configuring the right addresses is run. In that way no overlapping will happen, as the main ranges are already set.

Well, I guess we'll just have to wait for some real coder champion to step forward for that to be automatized

For the reference, here are my fixed DSDT and lspci -v from linux.

Attached File  acer_aspire_7730g_fixed_dsdt.dsl.txt ( 299.76K ) Number of downloads: 78

Attached File  lspci_linux.log.txt ( 12.04K ) Number of downloads: 51
Shauno
post Dec 30 2011, 06:54 PM
Post #4
Hello Darkuttek,

Having the same problems that you had and I'm attempting to follow your tutorial, thanks for the tut by the way.

YoYoost
post Jul 17 2012, 05:36 PM
Post #5
I have the same laptop as darkuttek: an Acer Aspire 7730 and I successfully used this tutorial.

Some problems I had: Used iAtkos S3 v2 to install OSX, solution: use Pirate EDI X v3 with the bootloader install on the .iso to install vanilla OSX Snow Leopard

After that I still had some problems with my com.apple.boot.plist settings, the look like this now
CODE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>DSDT</key>
    <string>/Extra/DSDT.aml</string>
    <key>Default Partition</key>
    <string>hd(0,2)</string>
    <key>GraphicsEnabler</key>
    <string>Yes</string>
    <key>Kernel Flags</key>
    <string>arch=i386</string>
    <key>Timeout</key>
    <string>5</string>
</dict>
</plist>


You could add some more stuff but change one thing at a time and reboot a few times to make sure it works!

I changed the settings with and app called Champlist.
I don't think this works with updated versions of Chameleon: I got kernel panics
I didn't try to update my system yet, but I also doubt this will work with anything other than 10.6.4

This post has been edited by YoYoost: Jul 17 2012, 05:37 PM

Add Reply Start a new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members: