To enable native QE graphics output on an ATI graphics adapter, you always need a framebuffer.
Either a pre-definded framebuffer can be used, or you can patch an existing one to match your graphics adapter's configuration of DVI/HDMI/VGA/Displayport.
Under OSX the ATI driver uses a hard-coded set of personalities to define some of the video card's capabilities, most notably the connector layout. This is sufficient to support the limited number of configurations that Apple ships, but leads to non-working monitors (black displays) in many hackintosh configurations. Users have limited success & limited functionality by simply guessing which hard-coded personality best matches their video card.
Some prerequisites:
Some prerequisites:
- Installation of OSX Developer tools (for examining personalities with otools)
- Somewhat working install of ATI radeon HD[45]xx card with Kabyl's chameleon branch:http://www.insanelymac.com/forum/index.php?showtopic=231768
- Understanding of hex editing
- Ability to troubleshoot by looking at ioregistry, understanding how to test ATI personalities using ATIConfig
Each of these personalities defines a set of hard-coded information about the video card hardware. One of the key pieces that gets defined is the connector information, known as ConnectorInfo within the ATI driver.
There is one ConnectorInfo structure for every potential connector that may be plugged into a video card. (Dual link DVI ports still count as a single ConnectorInfo). Each personality defines a table of these ConnectorInfo structures.
The ConnectorInfo structure can be represented as the following 16 byte structure, in C code:
CODE
typedef struct {
int ConnectorType; /* known values below */
#define CONNECTORTYPE_LVDS 0x00000002 /* Ie internal Low Voltage display,
such as laptop */
#define CONNECTORTYPE_DVI_DUAL 0x00000004 /* Dual link(?) DVI */
#define CONNECTORTYPE_VGA 0x00000010 /* Per mucha */
#define CONNECTORTYPE_SVIDEO 0x00000080 /* Per mucha */
#define CONNECTORTYPE_DVI 0x00000200 /* Single link DVI(?), Per azimutz */
#define CONNECTORTYPE_DP 0x00000400 /* Displayport */
#define CONNECTORTYPE_HDMI 0x00000800
int controlflags;
int features;
byte link_i2cid; /* Bits 0-3: i2cid
Bits 4-7: link transmitter link */
byte dac_digidx; /* Bits 0-3: link encoder number
Bits 4-7: link dac number */
byte hotplugid;
byte senseid; /* Sense line is bits 0-3
Use hw i2c flag is bit 4 */
/* i2cid = (senseid & 0xf-1)+0x90 */
/* senseid = (i2cid & 0xf) +1*/
} ConnectorInfo;
int ConnectorType; /* known values below */
#define CONNECTORTYPE_LVDS 0x00000002 /* Ie internal Low Voltage display,
such as laptop */
#define CONNECTORTYPE_DVI_DUAL 0x00000004 /* Dual link(?) DVI */
#define CONNECTORTYPE_VGA 0x00000010 /* Per mucha */
#define CONNECTORTYPE_SVIDEO 0x00000080 /* Per mucha */
#define CONNECTORTYPE_DVI 0x00000200 /* Single link DVI(?), Per azimutz */
#define CONNECTORTYPE_DP 0x00000400 /* Displayport */
#define CONNECTORTYPE_HDMI 0x00000800
int controlflags;
int features;
byte link_i2cid; /* Bits 0-3: i2cid
Bits 4-7: link transmitter link */
byte dac_digidx; /* Bits 0-3: link encoder number
Bits 4-7: link dac number */
byte hotplugid;
byte senseid; /* Sense line is bits 0-3
Use hw i2c flag is bit 4 */
/* i2cid = (senseid & 0xf-1)+0x90 */
/* senseid = (i2cid & 0xf) +1*/
} ConnectorInfo;
where integers are represented in intel little-endian byte order, and bit 0 is the LSB.
Lets take a look at the driver's 32-bit code for seting up the ConnectorInfo.
otool -arch i386 -vt ATIFramebuffer | c++filt | grep createInfo
gives you the list of the 26 initialization routines.
For all personalities, the initialization routine sets the connector count and a pointer to a static array of ConnectorInfo.
I've written a script which will parse the personality initialization routines for you and calculate the effective address of the ConnectorInfo table, as well as the number of table entries. The script currently outputs information for all personalities found in the ATI Framebuffer kext.
Usage:
perl ati-personality.pl
to output 32-bit kext information, or
perl ati-personality.pl -x
to output 64-bit kext information
As of osx 10.7, the connectorinfo has been separated out across several ATI controller kexts, instead of ATIFramebuffer.
The script detects this automatically for 10.7 and prints information for all the controller kexts. However the 10.6.7 2011 MBP kexts also share this new layout and the script doesn't auto-detect this. For this case only, you should use the -a switch to tell the script to look in the new locations:
perl ati-personality.pl -a
to get the connectorinfo from their new locations with the 10.6.7 2011 MBP kexts.
See finding-patch-address.txt in the attached zip file for instructions if you wish to calculate the effective address & disk address yourself by hand.
Note: ati-personality.pl supports OSX 10.6.x where x >= 4, and 10.7. In older versions of OSX the ConnectorInfo structure was a different length (used to be 20 bytes instead of the current 16).
ati_personality.pl.0.7.zip ( 3.99K ) Number of downloads: 856
For example purposes lets focus on the 10.6.6 32-bit portion of the kext, and the uakari ConnectorInfo. From ati-personality.pl we learn:
CODE
Personality: Uakari
ConnectorInfo count in decimal: 4
Disk offset in decimal 226552
0000000 00 04 00 00 00 04 00 00 00 01 00 00 12 04 04 01
0000010 04 00 00 00 14 00 00 00 00 01 00 00 01 12 01 03
0000020 00 02 00 00 14 00 00 00 00 01 00 00 00 00 06 05
0000030 00 08 00 00 00 02 00 00 00 01 00 00 22 05 05 04
0000040
ConnectorInfo count in decimal: 4
Disk offset in decimal 226552
0000000 00 04 00 00 00 04 00 00 00 01 00 00 12 04 04 01
0000010 04 00 00 00 14 00 00 00 00 01 00 00 01 12 01 03
0000020 00 02 00 00 14 00 00 00 00 01 00 00 00 00 06 05
0000030 00 08 00 00 00 02 00 00 00 01 00 00 22 05 05 04
0000040
You can see above that the perl script found the location of the Uakari connector info and has dumped out the contents in hex.
You can also dump the ConnectorInfo yourself, see the xxd example below.
Next we take a look at the ConnectorInfo for this personality:
connector-type 0x00000400=displayport at port 0
connector-type 0x00000004=DVI at port 1
connector-type 0x00000200=single link DVI(probably) at port 2
connector-type 0x00000800=HDMI at port 3
Booting kabyl's chameleon branch on my Sapphire Radeon 5670 with this personality results in working DVI and working HDMI (with no audio). Note that due to a bug in that code, overriding the personality from Baboon (the default with 3 connectors total) to Uakari results in 3 injection strings not 4. So the 5670 hardware's ports are matched against only the first 3 entries in the uakari table.
Looking at the ioregistry, one can see that port-number 1&2 matched and port 0 did not. (ATY_ActiveFlags != 1 when the port is matched).
So my HDMI port was matched but with the wrong connector type (0x0002). This causes HDMI audio to fail.
To fix this I overwrote bytes 0 thru 15 of port 2's table entry with port 3's.
You can do this using your favorite hex editor.
xxd, followed by ascii editing, followed by xxd -r is probably the simplest choice. For example:
CODE
% cd /System/Library/Extensions/ATIFramebuffer.kext/Contents/MacOS/
% ls -l ATIFramebuffer
-rw-r--r-- 1 root wheel 304556 Mar 2 16:57 ATIFramebuffer
% dd if=ATIFramebuffer of=/tmp/uakari bs=1 skip=226552 count=64
% cd /tmp
% xxd < uakari > hex
% cat hex
0000000: 0004 0000 0004 0000 0001 0000 1204 0401 ................
0000010: 0400 0000 1400 0000 0001 0000 0112 0103 ................
0000020: 0002 0000 1400 0000 0001 0000 0000 0605 ................
0000030: 0008 0000 0002 0000 0001 0000 2205 0504 ............"...
%
Since there are 4 connectors for this personality, we dump 4*16=64 bytes in the dd command shown above.% ls -l ATIFramebuffer
-rw-r--r-- 1 root wheel 304556 Mar 2 16:57 ATIFramebuffer
% dd if=ATIFramebuffer of=/tmp/uakari bs=1 skip=226552 count=64
% cd /tmp
% xxd < uakari > hex
% cat hex
0000000: 0004 0000 0004 0000 0001 0000 1204 0401 ................
0000010: 0400 0000 1400 0000 0001 0000 0112 0103 ................
0000020: 0002 0000 1400 0000 0001 0000 0000 0605 ................
0000030: 0008 0000 0002 0000 0001 0000 2205 0504 ............"...
%
Now you edit the ConnectoIinfo table with your favorite text editor and dd the result back in place:
CODE
% xxd -r < hex > uakari.new
% dd if=uakari.new of=/System/Library/Extensions/ATIFramebuffer.kext/Contents/MacOS/ATIFramebuffer bs=1 count=64 seek=226552 conv=notrunc
% dd if=uakari.new of=/System/Library/Extensions/ATIFramebuffer.kext/Contents/MacOS/ATIFramebuffer bs=1 count=64 seek=226552 conv=notrunc
The resulting table with the 3rd row changed:
CODE
% cat hex
0000000: 0004 0000 0004 0000 0001 0000 1204 0401 ................
0000010: 0400 0000 1400 0000 0001 0000 0112 0103 ................
0000020: 0008 0000 0002 0000 0001 0000 2205 0505 ............"...
0000030: 0008 0000 0002 0000 0001 0000 2205 0504 ............"...
0000000: 0004 0000 0004 0000 0001 0000 1204 0401 ................
0000010: 0400 0000 1400 0000 0001 0000 0112 0103 ................
0000020: 0008 0000 0002 0000 0001 0000 2205 0505 ............"...
0000030: 0008 0000 0002 0000 0001 0000 2205 0504 ............"...
Note that since the 32bit & 64bit connectorinfo tables are the same, you can simply repeat the last dd step above with the proper disk offset for the 64 bit table, in order to update that table as well.
With the above edit, my HDMI audio port is recognized as type 0x0800, with the usual HDMI flags, but with the expected sense line (0x05). And viola, HDMI audio now works!
Next, my Sapphire radeon 5670 actually has 3 ports - HDMI, DVI and displayport, and, alas, this personality is only working with 2 of them, even though the personality does include a displayport connector. Luckily I was able to find a different personality with which this card's displayport did work, the Vervet personality.
Again from ati-personality.pl, we find Vervet's ConnectorInfo:
CODE
Personality: Vervet
ConnectorInfo count in decimal: 4
Disk offset in decimal 226616
0000000 00 04 00 00 00 04 00 00 00 01 00 00 12 04 04 02
0000010 04 00 00 00 14 00 00 00 00 01 00 00 01 12 01 04
0000020 00 02 00 00 14 00 00 00 00 01 00 00 00 00 06 03
0000030 00 08 00 00 00 02 00 00 00 01 00 00 22 05 05 01
0000040
ConnectorInfo count in decimal: 4
Disk offset in decimal 226616
0000000 00 04 00 00 00 04 00 00 00 01 00 00 12 04 04 02
0000010 04 00 00 00 14 00 00 00 00 01 00 00 01 12 01 04
0000020 00 02 00 00 14 00 00 00 00 01 00 00 00 00 06 03
0000030 00 08 00 00 00 02 00 00 00 01 00 00 22 05 05 01
0000040
My card does in fact match port-number 0 for the DP port, as seen in the ioregistry.
So I copy the working senseid field from the vervet personality into the Uakari personality (replace the 0x01 at byte 15 of the first line with 0x02).
Viola, all 3 ports are now working with my card...
Hope this helps others with non-working ports or with HDMI audio problems.
Questions/comments?
Made by bcc9
Post a Comment