Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/i386/libsaio/nvidia.c

Source at commit 214 created 13 years 5 months ago.
By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings.
1/*
2 * NVidia injector
3 *
4 * Copyright (C) 2009 Jasmin Fazlic, iNDi
5 *
6 * NVidia injector is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * NVidia driver and injector is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with NVidia injector. If not, see <http://www.gnu.org/licenses/>.
18 */
19/*
20 * Alternatively you can choose to comply with APSL
21 */
22
23
24/*
25 * DCB-Table parsing is based on software (nouveau driver) originally distributed under following license:
26 *
27 *
28 * Copyright 2005-2006 Erik Waling
29 * Copyright 2006 Stephane Marchesin
30 * Copyright 2007-2009 Stuart Bennett
31 *
32 * Permission is hereby granted, free of charge, to any person obtaining a
33 * copy of this software and associated documentation files (the "Software"),
34 * to deal in the Software without restriction, including without limitation
35 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
36 * and/or sell copies of the Software, and to permit persons to whom the
37 * Software is furnished to do so, subject to the following conditions:
38 *
39 * The above copyright notice and this permission notice shall be included in
40 * all copies or substantial portions of the Software.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
45 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
46 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
47 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
48 * SOFTWARE.
49 */
50
51#include "libsaio.h"
52#include "boot.h"
53#include "bootstruct.h"
54#include "pci.h"
55#include "platform.h"
56#include "device_inject.h"
57#include "nvidia.h"
58
59#ifndef DEBUG_NVIDIA
60#define DEBUG_NVIDIA 0
61#endif
62
63#if DEBUG_NVIDIA
64#define DBG(x...)printf(x)
65#else
66#define DBG(x...)
67#endif
68
69#define NVIDIA_ROM_SIZE 0x10000
70#define PATCH_ROM_SUCCESS 1
71#define PATCH_ROM_SUCCESS_HAS_LVDS 2
72#define PATCH_ROM_FAILED 0
73#define MAX_NUM_DCB_ENTRIES 16
74
75#define TYPE_GROUPED 0xff
76
77extern uint32_t devices_number;
78
79const char *nvidia_compatible_0[]={ "@0,compatible","NVDA,NVMac" };
80const char *nvidia_compatible_1[]={ "@1,compatible","NVDA,NVMac" };
81const char *nvidia_device_type_0[]={ "@0,device_type","display" };
82const char *nvidia_device_type_1[]={ "@1,device_type","display" };
83const char *nvidia_device_type[]={ "device_type","NVDA,Parent" };
84const char *nvidia_name_0[]={ "@0,name","NVDA,Display-A" };
85const char *nvidia_name_1[]={ "@1,name","NVDA,Display-B" };
86const char *nvidia_slot_name[]={ "AAPL,slot-name","Slot-1" };
87
88static uint8_t default_NVCAP[]= {
890x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
900x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
910x00, 0x00, 0x00, 0x00
92};
93
94#define NVCAP_LEN ( sizeof(default_NVCAP) / sizeof(uint8_t) )
95
96static struct nv_chipsets_t NVKnownChipsets[] = {
97{ 0x00000000, "Unknown" },
98{ 0x10DE0040, "GeForce 6800 Ultra" },
99{ 0x10DE0041, "GeForce 6800" },
100{ 0x10DE0042, "GeForce 6800 LE" },
101{ 0x10DE0043, "GeForce 6800 XE" },
102{ 0x10DE0044, "GeForce 6800 XT" },
103{ 0x10DE0045, "GeForce 6800 GT" },
104{ 0x10DE0046, "GeForce 6800 GT" },
105{ 0x10DE0047, "GeForce 6800 GS" },
106{ 0x10DE0048, "GeForce 6800 XT" },
107{ 0x10DE004E, "Quadro FX 4000" },
108{ 0x10DE0090, "GeForce 7800 GTX" },
109{ 0x10DE0091, "GeForce 7800 GTX" },
110{ 0x10DE0092, "GeForce 7800 GT" },
111{ 0x10DE0093, "GeForce 7800 GS" },
112{ 0x10DE0095, "GeForce 7800 SLI" },
113{ 0x10DE0098, "GeForce Go 7800" },
114{ 0x10DE0099, "GeForce Go 7800 GTX" },
115{ 0x10DE009D, "Quadro FX 4500" },
116{ 0x10DE00C0, "GeForce 6800 GS" },
117{ 0x10DE00C1, "GeForce 6800" },
118{ 0x10DE00C2, "GeForce 6800 LE" },
119{ 0x10DE00C3, "GeForce 6800 XT" },
120{ 0x10DE00C8, "GeForce Go 6800" },
121{ 0x10DE00C9, "GeForce Go 6800 Ultra" },
122{ 0x10DE00CC, "Quadro FX Go1400" },
123{ 0x10DE00CD, "Quadro FX 3450/4000 SDI" },
124{ 0x10DE00CE, "Quadro FX 1400" },
125{ 0x10DE0140, "GeForce 6600 GT" },
126{ 0x10DE0141, "GeForce 6600" },
127{ 0x10DE0142, "GeForce 6600 LE" },
128{ 0x10DE0143, "GeForce 6600 VE" },
129{ 0x10DE0144, "GeForce Go 6600" },
130{ 0x10DE0145, "GeForce 6610 XL" },
131{ 0x10DE0146, "GeForce Go 6600 TE/6200 TE" },
132{ 0x10DE0147, "GeForce 6700 XL" },
133{ 0x10DE0148, "GeForce Go 6600" },
134{ 0x10DE0149, "GeForce Go 6600 GT" },
135{ 0x10DE014C, "Quadro FX 550" },
136{ 0x10DE014D, "Quadro FX 550" },
137{ 0x10DE014E, "Quadro FX 540" },
138{ 0x10DE014F, "GeForce 6200" },
139{ 0x10DE0160, "GeForce 6500" },
140{ 0x10DE0161, "GeForce 6200 TurboCache(TM)" },
141{ 0x10DE0162, "GeForce 6200SE TurboCache(TM)" },
142{ 0x10DE0163, "GeForce 6200 LE" },
143{ 0x10DE0164, "GeForce Go 6200" },
144{ 0x10DE0165, "Quadro NVS 285" },
145{ 0x10DE0166, "GeForce Go 6400" },
146{ 0x10DE0167, "GeForce Go 6200" },
147{ 0x10DE0168, "GeForce Go 6400" },
148{ 0x10DE0169, "GeForce 6250" },
149{ 0x10DE016A, "GeForce 7100 GS" },
150{ 0x10DE0191, "GeForce 8800 GTX" },
151{ 0x10DE0193, "GeForce 8800 GTS" },
152{ 0x10DE0194, "GeForce 8800 Ultra" },
153{ 0x10DE019D, "Quadro FX 5600" },
154{ 0x10DE019E, "Quadro FX 4600" },
155{ 0x10DE01D1, "GeForce 7300 LE" },
156{ 0x10DE01D3, "GeForce 7300 SE" },
157{ 0x10DE01D6, "GeForce Go 7200" },
158{ 0x10DE01D7, "GeForce Go 7300" },
159{ 0x10DE01D8, "GeForce Go 7400" },
160{ 0x10DE01D9, "GeForce Go 7400 GS" },
161{ 0x10DE01DA, "Quadro NVS 110M" },
162{ 0x10DE01DB, "Quadro NVS 120M" },
163{ 0x10DE01DC, "Quadro FX 350M" },
164{ 0x10DE01DD, "GeForce 7500 LE" },
165{ 0x10DE01DE, "Quadro FX 350" },
166{ 0x10DE01DF, "GeForce 7300 GS" },
167{ 0x10DE0211, "GeForce 6800" },
168{ 0x10DE0212, "GeForce 6800 LE" },
169{ 0x10DE0215, "GeForce 6800 GT" },
170{ 0x10DE0218, "GeForce 6800 XT" },
171{ 0x10DE0221, "GeForce 6200" },
172{ 0x10DE0222, "GeForce 6200 A-LE" },
173{ 0x10DE0240, "GeForce 6150" },
174{ 0x10DE0241, "GeForce 6150 LE" },
175{ 0x10DE0242, "GeForce 6100" },
176{ 0x10DE0244, "GeForce Go 6150" },
177{ 0x10DE0247, "GeForce Go 6100" },
178{ 0x10DE0290, "GeForce 7900 GTX" },
179{ 0x10DE0291, "GeForce 7900 GT" },
180{ 0x10DE0292, "GeForce 7900 GS" },
181{ 0x10DE0298, "GeForce Go 7900 GS" },
182{ 0x10DE0299, "GeForce Go 7900 GTX" },
183{ 0x10DE029A, "Quadro FX 2500M" },
184{ 0x10DE029B, "Quadro FX 1500M" },
185{ 0x10DE029C, "Quadro FX 5500" },
186{ 0x10DE029D, "Quadro FX 3500" },
187{ 0x10DE029E, "Quadro FX 1500" },
188{ 0x10DE029F, "Quadro FX 4500 X2" },
189{ 0x10DE0301, "GeForce FX 5800 Ultra" },
190{ 0x10DE0302, "GeForce FX 5800" },
191{ 0x10DE0308, "Quadro FX 2000" },
192{ 0x10DE0309, "Quadro FX 1000" },
193{ 0x10DE0311, "GeForce FX 5600 Ultra" },
194{ 0x10DE0312, "GeForce FX 5600" },
195{ 0x10DE0314, "GeForce FX 5600XT" },
196{ 0x10DE031A, "GeForce FX Go5600" },
197{ 0x10DE031B, "GeForce FX Go5650" },
198{ 0x10DE031C, "Quadro FX Go700" },
199{ 0x10DE0324, "GeForce FX Go5200" },
200{ 0x10DE0325, "GeForce FX Go5250" },
201{ 0x10DE0326, "GeForce FX 5500" },
202{ 0x10DE0328, "GeForce FX Go5200 32M/64M" },
203{ 0x10DE032A, "Quadro NVS 55/280 PCI" },
204{ 0x10DE032B, "Quadro FX 500/600 PCI" },
205{ 0x10DE032C, "GeForce FX Go53xx Series" },
206{ 0x10DE032D, "GeForce FX Go5100" },
207{ 0x10DE0330, "GeForce FX 5900 Ultra" },
208{ 0x10DE0331, "GeForce FX 5900" },
209{ 0x10DE0332, "GeForce FX 5900XT" },
210{ 0x10DE0333, "GeForce FX 5950 Ultra" },
211{ 0x10DE0334, "GeForce FX 5900ZT" },
212{ 0x10DE0338, "Quadro FX 3000" },
213{ 0x10DE033F, "Quadro FX 700" },
214{ 0x10DE0341, "GeForce FX 5700 Ultra" },
215{ 0x10DE0342, "GeForce FX 5700" },
216{ 0x10DE0343, "GeForce FX 5700LE" },
217{ 0x10DE0344, "GeForce FX 5700VE" },
218{ 0x10DE0347, "GeForce FX Go5700" },
219{ 0x10DE0348, "GeForce FX Go5700" },
220{ 0x10DE034C, "Quadro FX Go1000" },
221{ 0x10DE034E, "Quadro FX 1100" },
222{ 0x10DE0391, "GeForce 7600 GT" },
223{ 0x10DE0392, "GeForce 7600 GS" },
224{ 0x10DE0393, "GeForce 7300 GT" },
225{ 0x10DE0394, "GeForce 7600 LE" },
226{ 0x10DE0395, "GeForce 7300 GT" },
227{ 0x10DE0397, "GeForce Go 7700" },
228{ 0x10DE0398, "GeForce Go 7600" },
229{ 0x10DE0399, "GeForce Go 7600 GT"},
230{ 0x10DE039A, "Quadro NVS 300M" },
231{ 0x10DE039B, "GeForce Go 7900 SE" },
232{ 0x10DE039C, "Quadro FX 550M" },
233{ 0x10DE039E, "Quadro FX 560" },
234{ 0x10DE0400, "GeForce 8600 GTS" },
235{ 0x10DE0401, "GeForce 8600 GT" },
236{ 0x10DE0402, "GeForce 8600 GT" },
237{ 0x10DE0403, "GeForce 8600 GS" },
238{ 0x10DE0404, "GeForce 8400 GS" },
239{ 0x10DE0405, "GeForce 9500M GS" },
240{ 0x10DE0407, "GeForce 8600M GT" },
241{ 0x10DE0408, "GeForce 9650M GS" },
242{ 0x10DE0409, "GeForce 8700M GT" },
243{ 0x10DE040A, "Quadro FX 370" },
244{ 0x10DE040B, "Quadro NVS 320M" },
245{ 0x10DE040C, "Quadro FX 570M" },
246{ 0x10DE040D, "Quadro FX 1600M" },
247{ 0x10DE040E, "Quadro FX 570" },
248{ 0x10DE040F, "Quadro FX 1700" },
249{ 0x10DE0420, "GeForce 8400 SE" },
250{ 0x10DE0421, "GeForce 8500 GT" },
251{ 0x10DE0422, "GeForce 8400 GS" },
252{ 0x10DE0423, "GeForce 8300 GS" },
253{ 0x10DE0424, "GeForce 8400 GS" },
254{ 0x10DE0425, "GeForce 8600M GS" },
255{ 0x10DE0426, "GeForce 8400M GT" },
256{ 0x10DE0427, "GeForce 8400M GS" },
257{ 0x10DE0428, "GeForce 8400M G" },
258{ 0x10DE0429, "Quadro NVS 140M" },
259{ 0x10DE042A, "Quadro NVS 130M" },
260{ 0x10DE042B, "Quadro NVS 135M" },
261{ 0x10DE042C, "GeForce 9400 GT" },
262{ 0x10DE042D, "Quadro FX 360M" },
263{ 0x10DE042E, "GeForce 9300M G" },
264{ 0x10DE042F, "Quadro NVS 290" },
265{ 0x10DE05E0, "GeForce GTX 295" },
266{ 0x10DE05E1, "GeForce GTX 280" },
267{ 0x10DE05E2, "GeForce GTX 260" },
268{ 0x10DE05E3, "GeForce GTX 285" },
269{ 0x10DE05E6, "GeForce GTX 275" },
270{ 0x10DE05EA, "GeForce GTX 260" },
271{ 0x10DE05EB, "GeForce GTX 295" },
272{ 0x10DE05F9, "Quadro CX" },
273{ 0x10DE05FD, "Quadro FX 5800" },
274{ 0x10DE05FE, "Quadro FX 4800" },
275{ 0x10DE0600, "GeForce 8800 GTS 512" },
276{ 0x10DE0602, "GeForce 8800 GT" },
277{ 0x10DE0604, "GeForce 9800 GX2" },
278{ 0x10DE0605, "GeForce 9800 GT" },
279{ 0x10DE0606, "GeForce 8800 GS" },
280{ 0x10DE0607, "GeForce GTS 240" },
281{ 0x10DE0608, "GeForce 9800M GTX" },
282{ 0x10DE0609, "GeForce 8800M GTS" },
283{ 0x10DE060A, "GeForce GTX 280M" },
284{ 0x10DE060B, "GeForce 9800M GT" },
285{ 0x10DE060C, "GeForce 8800M GTX" },
286{ 0x10DE060D, "GeForce 8800 GS" },
287{ 0x10DE0610, "GeForce 9600 GSO" },
288{ 0x10DE0611, "GeForce 8800 GT" },
289{ 0x10DE0612, "GeForce 9800 GTX" },
290{ 0x10DE0613, "GeForce 9800 GTX+" },
291{ 0x10DE0614, "GeForce 9800 GT" },
292{ 0x10DE0615, "GeForce GTS 250" },
293{ 0x10DE0617, "GeForce 9800M GTX" },
294{ 0x10DE0618, "GeForce GTX 260M" },
295{ 0x10DE061A, "Quadro FX 3700" },
296{ 0x10DE061C, "Quadro FX 3600M" },
297{ 0x10DE061D, "Quadro FX 2800M" },
298{ 0x10DE061F, "Quadro FX 3800M" },
299{ 0x10DE0622, "GeForce 9600 GT" },
300{ 0x10DE0623, "GeForce 9600 GS" },
301{ 0x10DE0625, "GeForce 9600 GSO 512"},
302{ 0x10DE0626, "GeForce GT 130" },
303{ 0x10DE0627, "GeForce GT 140" },
304{ 0x10DE0628, "GeForce 9800M GTS" },
305{ 0x10DE062A, "GeForce 9700M GTS" },
306{ 0x10DE062C, "GeForce 9800M GTS" },
307{ 0x10DE0640, "GeForce 9500 GT" },
308{ 0x10DE0641, "GeForce 9400 GT" },
309{ 0x10DE0642, "GeForce 8400 GS" },
310{ 0x10DE0643, "GeForce 9500 GT" },
311{ 0x10DE0644, "GeForce 9500 GS" },
312{ 0x10DE0645, "GeForce 9500 GS" },
313{ 0x10DE0646, "GeForce GT 120" },
314{ 0x10DE0647, "GeForce 9600M GT" },
315{ 0x10DE0648, "GeForce 9600M GS" },
316{ 0x10DE0649, "GeForce 9600M GT" },
317{ 0x10DE064A, "GeForce 9700M GT" },
318{ 0x10DE064B, "GeForce 9500M G" },
319{ 0x10DE064C, "GeForce 9650M GT" },
320{ 0x10DE0652, "GeForce GT 130M" },
321{ 0x10DE0658, "Quadro FX 380" },
322{ 0x10DE0659, "Quadro FX 580" },
323{ 0x10DE065A, "Quadro FX 1700M" },
324{ 0x10DE065B, "GeForce 9400 GT" },
325{ 0x10DE065C, "Quadro FX 770M" },
326{ 0x10DE06C0, "GeForce GTX 480" },
327{ 0x10DE06C4, "GeForce GTX 465" },
328{ 0x10DE06CA, "GeForce GTX 480M" },
329{ 0x10DE06CD, "GeForce GTX 470" },
330{ 0x10DE06E0, "GeForce 9300 GE" },
331{ 0x10DE06E1, "GeForce 9300 GS" },
332{ 0x10DE06E4, "GeForce 8400 GS" },
333{ 0x10DE06E5, "GeForce 9300M GS" },
334{ 0x10DE06E8, "GeForce 9200M GS" },
335{ 0x10DE06E9, "GeForce 9300M GS" },
336{ 0x10DE06EA, "Quadro NVS 150M" },
337{ 0x10DE06EB, "Quadro NVS 160M" },
338{ 0x10DE06EC, "GeForce G 105M" },
339{ 0x10DE06EF, "GeForce G 103M" },
340{ 0x10DE06F8, "Quadro NVS 420" },
341{ 0x10DE06F9, "Quadro FX 370 LP" },
342{ 0x10DE06FA, "Quadro NVS 450" },
343{ 0x10DE06FD, "Quadro NVS 295" },
344{ 0x10DE086C, "GeForce 9300/nForce 730i" },
345{ 0x10DE087D, "ION 9400M" },
346{ 0x10DE087E, "ION LE" },
347{ 0x10DE0A20, "GeForce GT220" },
348{ 0x10DE0A23, "GeForce 210" },
349{ 0x10DE0A28, "GeForce GT 230M" },
350{ 0x10DE0A29, "GeForce GT 330M" },
351{ 0x10DE0A2A, "GeForce GT 230M" },
352{ 0x10DE0A34, "GeForce GT 240M" },
353{ 0x10DE0A60, "GeForce G210" },
354{ 0x10DE0A62, "GeForce 205" },
355{ 0x10DE0A63, "GeForce 310" },
356{ 0x10DE0A65, "GeForce 210" },
357{ 0x10DE0A66, "GeForce 310" },
358{ 0x10DE0A74, "GeForce G210M" },
359{ 0x10DE0A75, "GeForce G310M" },
360{ 0x10DE0A78, "Quadro FX 380 LP" },
361{ 0x10DE0CA3, "GeForce GT 240" },
362{ 0x10DE0CA8, "GeForce GTS 260M" },
363{ 0x10DE0CA9, "GeForce GTS 250M" },
364{ 0x10DE0CB1, "GeForce GTS 360M" },
365{ 0x10DE0CA3, "GeForce GT240" },
366{ 0x10DE0E22, "GeForce GTX 460" },
367{ 0x10DE0E24, "GeForce GTX 460" },
368{ 0x10DE06D1, "Tesla C2050" },// TODO: sub-device id: 0x0771
369{ 0x10DE06D1, "Tesla C2070" },// TODO: sub-device id: 0x0772
370{ 0x10DE06DE, "Tesla M2050" },// TODO: sub-device id: 0x0846
371{ 0x10DE06DE, "Tesla M2070" }// TODO: sub-device id: ?
372};
373
374static uint16_t swap16(uint16_t x)
375{
376return (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8));
377}
378
379static uint16_t read16(uint8_t *ptr, uint16_t offset)
380{
381uint8_t ret[2];
382ret[0] = ptr[offset+1];
383ret[1] = ptr[offset];
384return *((uint16_t*)&ret);
385}
386
387#if 0
388static uint32_t swap32(uint32_t x)
389{
390return ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8 ) | ((x & 0x00FF0000) >> 8 ) | ((x & 0xFF000000) >> 24);
391}
392
393static uint8_t read8(uint8_t *ptr, uint16_t offset)
394{
395return ptr[offset];
396}
397
398static uint32_t read32(uint8_t *ptr, uint16_t offset)
399{
400uint8_t ret[4];
401ret[0] = ptr[offset+3];
402ret[1] = ptr[offset+2];
403ret[2] = ptr[offset+1];
404ret[3] = ptr[offset];
405return *((uint32_t*)&ret);
406}
407#endif
408
409static int patch_nvidia_rom(uint8_t *rom)
410{
411if (!rom || (rom[0] != 0x55 && rom[1] != 0xaa)) {
412printf("False ROM signature: 0x%02x%02x\n", rom[0], rom[1]);
413return PATCH_ROM_FAILED;
414}
415
416uint16_t dcbptr = swap16(read16(rom, 0x36));
417if(!dcbptr) {
418printf("no dcb table found\n");
419return PATCH_ROM_FAILED;
420}/* else
421 printf("dcb table at offset 0x%04x\n", dcbptr);
422 */
423uint8_t *dcbtable = &rom[dcbptr];
424uint8_t dcbtable_version = dcbtable[0];
425uint8_t headerlength = 0;
426uint8_t recordlength = 0;
427uint8_t numentries = 0;
428
429if(dcbtable_version >= 0x20) {
430uint32_t sig;
431
432if(dcbtable_version >= 0x30) {
433headerlength = dcbtable[1];
434numentries = dcbtable[2];
435recordlength = dcbtable[3];
436sig = *(uint32_t *)&dcbtable[6];
437} else {
438sig = *(uint32_t *)&dcbtable[4];
439headerlength = 8;
440}
441if (sig != 0x4edcbdcb) {
442printf("bad display config block signature (0x%8x)\n", sig);
443return PATCH_ROM_FAILED;
444}
445} else if (dcbtable_version >= 0x14) { /* some NV15/16, and NV11+ */
446char sig[8] = { 0 };
447
448strncpy(sig, (char *)&dcbtable[-7], 7);
449recordlength = 10;
450if (strcmp(sig, "DEV_REC")) {
451printf("Bad Display Configuration Block signature (%s)\n", sig);
452return PATCH_ROM_FAILED;
453}
454} else {
455printf("ERROR: dcbtable_version is 0x%X\n", dcbtable_version);
456return PATCH_ROM_FAILED;
457}
458
459if(numentries >= MAX_NUM_DCB_ENTRIES)
460numentries = MAX_NUM_DCB_ENTRIES;
461
462uint8_t num_outputs = 0, i=0;
463struct dcbentry {
464uint8_t type;
465uint8_t index;
466uint8_t *heads;
467} entries[numentries];
468
469for (i = 0; i < numentries; i++) {
470uint32_t connection;
471connection = *(uint32_t *)&dcbtable[headerlength + recordlength * i];
472/* Should we allow discontinuous DCBs? Certainly DCB I2C tables can be discontinuous */
473if ((connection & 0x0000000f) == 0x0000000f) /* end of records */
474continue;
475if (connection == 0x00000000) /* seen on an NV11 with DCB v1.5 */
476continue;
477if ((connection & 0xf) == 0x6) /* we skip type 6 as it doesnt appear on macbook nvcaps */
478continue;
479
480entries[num_outputs].type = connection & 0xf;
481entries[num_outputs].index = num_outputs;
482entries[num_outputs++].heads = (uint8_t*)&(dcbtable[(headerlength + recordlength * i) + 1]);
483
484}
485
486int has_lvds = false;
487uint8_t channel1 = 0, channel2 = 0;
488
489for(i=0; i<num_outputs; i++) {
490if(entries[i].type == 3) {
491has_lvds = true;
492//printf("found LVDS\n");
493channel1 |= ( 0x1 << entries[i].index);
494entries[i].type = TYPE_GROUPED;
495}
496}
497// if we have a LVDS output, we group the rest to the second channel
498if(has_lvds) {
499for(i=0; i<num_outputs; i++) {
500if(entries[i].type == TYPE_GROUPED)
501continue;
502channel2 |= ( 0x1 << entries[i].index);
503entries[i].type = TYPE_GROUPED;
504}
505} else {
506//
507int x;
508// we loop twice as we need to generate two channels
509for(x=0; x<=1; x++) {
510for(i=0; i<num_outputs; i++) {
511if(entries[i].type == TYPE_GROUPED)
512continue;
513// if type is TMDS, the prior output is ANALOG
514// we always group ANALOG and TMDS
515// if there is a TV output after TMDS, we group it to that channel as well
516if(i && entries[i].type == 0x2) {
517switch (x) {
518case 0:
519//printf("group channel 1\n");
520channel1 |= ( 0x1 << entries[i].index);
521entries[i].type = TYPE_GROUPED;
522if((entries[i-1].type == 0x0)) {
523channel1 |= ( 0x1 << entries[i-1].index);
524entries[i-1].type = TYPE_GROUPED;
525}
526// group TV as well if there is one
527if( ((i+1) < num_outputs) && (entries[i+1].type == 0x1) ) {
528//printf("group tv1\n");
529channel1 |= ( 0x1 << entries[i+1].index);
530entries[i+1].type = TYPE_GROUPED;
531}
532break;
533case 1:
534//printf("group channel 2 : %d\n", i);
535channel2 |= ( 0x1 << entries[i].index);
536entries[i].type = TYPE_GROUPED;
537if((entries[i-1].type == 0x0)) {
538channel2 |= ( 0x1 << entries[i-1].index);
539entries[i-1].type = TYPE_GROUPED;
540}
541// group TV as well if there is one
542if( ((i+1) < num_outputs) && (entries[i+1].type == 0x1) ) {
543//printf("group tv2\n");
544channel2 |= ( 0x1 << entries[i+1].index);
545entries[i+1].type = TYPE_GROUPED;
546}
547break;
548
549}
550break;
551}
552}
553}
554}
555
556// if we have left ungrouped outputs merge them to the empty channel
557uint8_t *togroup;// = (channel1 ? (channel2 ? NULL : &channel2) : &channel1);
558togroup = &channel2;
559for(i=0; i<num_outputs;i++)
560if(entries[i].type != TYPE_GROUPED) {
561//printf("%d not grouped\n", i);
562if(togroup)
563*togroup |= ( 0x1 << entries[i].index);
564entries[i].type = TYPE_GROUPED;
565}
566
567if(channel1 > channel2) {
568uint8_t buff = channel1;
569channel1 = channel2;
570channel2 = buff;
571}
572
573default_NVCAP[6] = channel1;
574default_NVCAP[8] = channel2;
575
576// patching HEADS
577for(i=0; i<num_outputs;i++) {
578if(channel1 & (1 << i))
579*entries[i].heads = 1;
580else if(channel2 & (1 << i))
581*entries[i].heads = 2;
582}
583
584return (has_lvds ? PATCH_ROM_SUCCESS_HAS_LVDS : PATCH_ROM_SUCCESS);
585}
586
587static char *get_nvidia_model(uint32_t id) {
588inti;
589
590for (i=1; i< (sizeof(NVKnownChipsets) / sizeof(NVKnownChipsets[0])); i++) {
591if (NVKnownChipsets[i].device == id) {
592return NVKnownChipsets[i].name;
593}
594}
595return NVKnownChipsets[0].name;
596}
597
598static uint32_t load_nvidia_bios_file(const char *filename, uint8_t *buf, int bufsize)
599{
600intfd;
601intsize;
602
603if ((fd = open_bvdev("bt(0,0)", filename, 0)) < 0) {
604return 0;
605}
606size = file_size(fd);
607if (size > bufsize) {
608printf("Filesize of %s is bigger than expected! Truncating to 0x%x Bytes!\n", filename, bufsize);
609size = bufsize;
610}
611size = read(fd, (char *)buf, size);
612close(fd);
613return size > 0 ? size : 0;
614}
615
616static int devprop_add_nvidia_template(struct DevPropDevice *device)
617{
618chartmp[16];
619
620if(!device)
621return 0;
622
623if(!DP_ADD_TEMP_VAL(device, nvidia_compatible_0))
624return 0;
625if(!DP_ADD_TEMP_VAL(device, nvidia_device_type_0))
626return 0;
627if(!DP_ADD_TEMP_VAL(device, nvidia_name_0))
628return 0;
629if(!DP_ADD_TEMP_VAL(device, nvidia_compatible_1))
630return 0;
631if(!DP_ADD_TEMP_VAL(device, nvidia_device_type_1))
632return 0;
633if(!DP_ADD_TEMP_VAL(device, nvidia_name_1))
634return 0;
635if(!DP_ADD_TEMP_VAL(device, nvidia_device_type))
636return 0;
637// Rek : Dont use sprintf return, it does not WORK !! our custom sprintf() always return 0!
638// len = sprintf(tmp, "Slot-%x", devices_number);
639sprintf(tmp, "Slot-%x",devices_number);
640devprop_add_value(device, "AAPL,slot-name", (uint8_t *) tmp, strlen(tmp));
641devices_number++;
642
643return 1;
644}
645
646int hex2bin(const char *hex, uint8_t *bin, int len)
647{
648char*p;
649inti;
650charbuf[3];
651
652if (hex == NULL || bin == NULL || len <= 0 || strlen(hex) != len * 2) {
653printf("[ERROR] bin2hex input error\n");
654return -1;
655}
656
657buf[2] = '\0';
658p = (char *) hex;
659for (i=0; i<len; i++) {
660if (p[0] == '\0' || p[1] == '\0' || !isxdigit(p[0]) || !isxdigit(p[1])) {
661printf("[ERROR] bin2hex '%s' syntax error\n", hex);
662return -2;
663}
664buf[0] = *p++;
665buf[1] = *p++;
666bin[i] = (unsigned char) strtoul(buf, NULL, 16);
667}
668return 0;
669}
670
671unsigned long long mem_detect(volatile uint8_t *regs, uint8_t nvCardType, pci_dt_t *nvda_dev)
672{
673unsigned long long vram_size = 0;
674
675if (nvCardType < NV_ARCH_50) {
676vram_size = REG32(NV04_PFB_FIFO_DATA);
677vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
678}
679else if (nvCardType >= NV_ARCH_C0) {
680vram_size = REG32(NVC0_MEM_CTRLR_COUNT);
681vram_size *= REG32(NVC0_MEM_CTRLR_RAM_AMOUNT);
682vram_size <<= 20;
683}
684else {
685vram_size = REG32(NV04_PFB_FIFO_DATA);
686vram_size |= (vram_size & 0xff) << 32;
687vram_size &= 0xffffffff00ll;
688}
689
690return vram_size;
691}
692
693bool setup_nvidia_devprop(pci_dt_t *nvda_dev)
694{
695struct DevPropDevice*device;
696char*devicepath;
697struct pci_rom_pci_header_t*rom_pci_header;
698volatile uint8_t*regs;
699uint8_t*rom;
700uint8_t*nvRom;
701uint8_tnvCardType;
702unsigned long longvideoRam;
703uint32_tnvBiosOveride;
704uint32_tbar[7];
705uint32_tboot_display;
706intnvPatch;
707intlen;
708charbiosVersion[32];
709charnvFilename[32];
710charkNVCAP[12];
711char*model;
712const char*value;
713booldoit;
714
715devicepath = get_pci_dev_path(nvda_dev);
716bar[0] = pci_config_read32(nvda_dev->dev.addr, 0x10 );
717regs = (uint8_t *) (bar[0] & ~0x0f);
718
719delay(50);
720
721// get card type
722nvCardType = (REG32(0) >> 20) & 0x1ff;
723
724// Amount of VRAM in kilobytes
725videoRam = mem_detect(regs, nvCardType, nvda_dev);
726model = get_nvidia_model((nvda_dev->vendor_id << 16) | nvda_dev->device_id);
727
728verbose("nVidia %s %dMB NV%02x [%04x:%04x] :: %s\n",
729model, (uint32_t)(videoRam / 1024 / 1024),
730(REG32(0) >> 20) & 0x1ff, nvda_dev->vendor_id, nvda_dev->device_id,
731devicepath);
732
733rom = malloc(NVIDIA_ROM_SIZE);
734sprintf(nvFilename, "/Extra/%04x_%04x.rom", (uint16_t)nvda_dev->vendor_id, (uint16_t)nvda_dev->device_id);
735if (getBoolForKey(kUseNvidiaROM, &doit, &bootInfo->bootConfig) && doit) {
736verbose("Looking for nvidia video bios file %s\n", nvFilename);
737nvBiosOveride = load_nvidia_bios_file(nvFilename, rom, NVIDIA_ROM_SIZE);
738if (nvBiosOveride > 0) {
739verbose("Using nVidia Video BIOS File %s (%d Bytes)\n", nvFilename, nvBiosOveride);
740DBG("%s Signature 0x%02x%02x %d bytes\n", nvFilename, rom[0], rom[1], nvBiosOveride);
741} else {
742printf("ERROR: unable to open nVidia Video BIOS File %s\n", nvFilename);
743return false;
744}
745} else {
746// Otherwise read bios from card
747nvBiosOveride = 0;
748
749// TODO: we should really check for the signature before copying the rom, i think.
750
751// PRAMIN first
752nvRom = (uint8_t*)&regs[NV_PRAMIN_OFFSET];
753bcopy((uint32_t *)nvRom, rom, NVIDIA_ROM_SIZE);
754
755// Valid Signature ?
756if (rom[0] != 0x55 && rom[1] != 0xaa) {
757// PROM next
758// Enable PROM access
759(REG32(NV_PBUS_PCI_NV_20)) = NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED;
760
761nvRom = (uint8_t*)&regs[NV_PROM_OFFSET];
762bcopy((uint8_t *)nvRom, rom, NVIDIA_ROM_SIZE);
763
764// disable PROM access
765(REG32(NV_PBUS_PCI_NV_20)) = NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED;
766
767// Valid Signature ?
768if (rom[0] != 0x55 && rom[1] != 0xaa) {
769// 0xC0000 last
770bcopy((char *)0xc0000, rom, NVIDIA_ROM_SIZE);
771
772// Valid Signature ?
773if (rom[0] != 0x55 && rom[1] != 0xaa) {
774printf("ERROR: Unable to locate nVidia Video BIOS\n");
775return false;
776} else {
777DBG("ROM Address 0x%x Signature 0x%02x%02x\n", nvRom, rom[0], rom[1]);
778}
779} else {
780DBG("PROM Address 0x%x Signature 0x%02x%02x\n", nvRom, rom[0], rom[1]);
781}
782} else {
783DBG("PRAM Address 0x%x Signature 0x%02x%02x\n", nvRom, rom[0], rom[1]);
784}
785}
786
787if ((nvPatch = patch_nvidia_rom(rom)) == PATCH_ROM_FAILED) {
788printf("ERROR: nVidia ROM Patching Failed!\n");
789return false;
790}
791
792rom_pci_header = (struct pci_rom_pci_header_t*)(rom + *(uint16_t *)&rom[24]);
793
794// check for 'PCIR' sig
795if (rom_pci_header->signature == 0x50434952) {
796if (rom_pci_header->device != nvda_dev->device_id) {
797// Get Model from the OpROM
798model = get_nvidia_model((rom_pci_header->vendor << 16) | rom_pci_header->device);
799} else {
800printf("nVidia incorrect PCI ROM signature: 0x%x\n", rom_pci_header->signature);
801}
802}
803
804if (!string) {
805string = devprop_create_string();
806}
807device = devprop_add_device(string, devicepath);
808
809/* FIXME: for primary graphics card only */
810boot_display = 1;
811devprop_add_value(device, "@0,AAPL,boot-display", (uint8_t*)&boot_display, 4);
812
813if(nvPatch == PATCH_ROM_SUCCESS_HAS_LVDS) {
814uint8_t built_in = 0x01;
815devprop_add_value(device, "@0,built-in", &built_in, 1);
816}
817
818// get bios version
819const int MAX_BIOS_VERSION_LENGTH = 32;
820char* version_str = (char*)malloc(MAX_BIOS_VERSION_LENGTH);
821memset(version_str, 0, MAX_BIOS_VERSION_LENGTH);
822int i, version_start;
823int crlf_count = 0;
824// only search the first 384 bytes
825for(i = 0; i < 0x180; i++) {
826if(rom[i] == 0x0D && rom[i+1] == 0x0A) {
827crlf_count++;
828// second 0x0D0A was found, extract bios version
829if(crlf_count == 2) {
830if(rom[i-1] == 0x20) i--; // strip last " "
831for(version_start = i; version_start > (i-MAX_BIOS_VERSION_LENGTH); version_start--) {
832// find start
833if(rom[version_start] == 0x00) {
834version_start++;
835
836// strip "Version "
837if(strncmp((const char*)rom+version_start, "Version ", 8) == 0) {
838version_start += 8;
839}
840
841strncpy(version_str, (const char*)rom+version_start, i-version_start);
842break;
843}
844}
845break;
846}
847}
848}
849
850sprintf(biosVersion, "%s", (nvBiosOveride > 0) ? nvFilename : version_str);
851
852sprintf(kNVCAP, "NVCAP_%04x", nvda_dev->device_id);
853if (getValueForKey(kNVCAP, &value, &len, &bootInfo->bootConfig) && len == NVCAP_LEN * 2) {
854uint8_tnew_NVCAP[NVCAP_LEN];
855
856if (hex2bin(value, new_NVCAP, NVCAP_LEN) == 0) {
857verbose("Using user supplied NVCAP for %s :: %s\n", model, devicepath);
858memcpy(default_NVCAP, new_NVCAP, NVCAP_LEN);
859}
860}
861
862 #if DEBUG_NVCAP
863 printf("NVCAP: %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x\n",
864default_NVCAP[0], default_NVCAP[1], default_NVCAP[2], default_NVCAP[3],
865default_NVCAP[4], default_NVCAP[5], default_NVCAP[6], default_NVCAP[7],
866default_NVCAP[8], default_NVCAP[9], default_NVCAP[10], default_NVCAP[11],
867default_NVCAP[12], default_NVCAP[13], default_NVCAP[14], default_NVCAP[15],
868default_NVCAP[16], default_NVCAP[17], default_NVCAP[18], default_NVCAP[19]);
869#endif
870
871
872devprop_add_nvidia_template(device);
873devprop_add_value(device, "NVCAP", default_NVCAP, NVCAP_LEN);
874devprop_add_value(device, "VRAM,totalsize", (uint8_t*)&videoRam, 4);
875devprop_add_value(device, "model", (uint8_t*)model, strlen(model) + 1);
876devprop_add_value(device, "rom-revision", (uint8_t*)biosVersion, strlen(biosVersion) + 1);
877if (getBoolForKey(kVBIOS, &doit, &bootInfo->bootConfig) && doit) {
878devprop_add_value(device, "vbios", rom, (nvBiosOveride > 0) ? nvBiosOveride : (rom[2] * 512));
879}
880
881stringdata = malloc(sizeof(uint8_t) * string->length);
882memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length);
883stringlength = string->length;
884
885return true;
886}
887

Archive Download this file

Revision: 214