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;
}
}
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;
}
{
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;
}
}
// 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;
}
}
// 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;
}
}
{
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.





May 4 2011, 10:14 PM


