1 | /*␊ |
2 | * nvidia_resolution.c␊ |
3 | * ␊ |
4 | *␊ |
5 | * Created by Le Bidou on 19/03/10.␊ |
6 | * Copyright 2010 ---. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include "nvidia_resolution.h"␊ |
11 | ␊ |
12 | vbios_map * open_nvidia_vbios(vbios_map *map)␊ |
13 | {␊ |
14 | ␉unsigned short nv_data_table_offset = 0;␊ |
15 | ␉unsigned short nv_modeline_2_offset = 0;␊ |
16 | ␉unsigned short * nv_data_table = NULL;␊ |
17 | ␉NV_VESA_TABLE * std_vesa;␊ |
18 | ␉␊ |
19 | ␉/*␊ |
20 | ␉ * Locate the VESA Tables␊ |
21 | ␉ */␊ |
22 | ␉␊ |
23 | ␉int i = 0;␊ |
24 | ␉␊ |
25 | ␉while (i < 0x300) { //We don't need to look for the table in the whole bios, the 768 first bytes only␊ |
26 | ␉␉if ((map->bios_ptr[i] == 0x44) ␊ |
27 | ␉␉␉&& (map->bios_ptr[i+1] == 0x01) ␊ |
28 | ␉␉␉&& (map->bios_ptr[i+2] == 0x04) ␊ |
29 | ␉␉␉&& (map->bios_ptr[i+3] == 0x00)) {␊ |
30 | ␉␉␉nv_data_table_offset = (unsigned short) (map->bios_ptr[i+4] | (map->bios_ptr[i+5] << 8));␊ |
31 | ␉␉␉break;␊ |
32 | ␉␉}␊ |
33 | ␉␉i++;␊ |
34 | ␉}␊ |
35 | ␉//Second VESA Table on some nVidia 8xxx 9xxx and GT␊ |
36 | ␉while (i < VBIOS_SIZE) { //We don't know how to locate it other way␊ |
37 | ␉␉if ((map->bios_ptr[i] == 0x40) && (map->bios_ptr[i+1] == 0x01) //this is the first 320x200 modeline.␊ |
38 | ␉␉␉&& (map->bios_ptr[i+2] == 0xC8) && (map->bios_ptr[i+3] == 0x00)␊ |
39 | ␉␉␉&& (map->bios_ptr[i+4] == 0x28)␊ |
40 | ␉␉␉&& (map->bios_ptr[i+5] == 0x18)␊ |
41 | ␉␉␉&& (map->bios_ptr[i+6] == 0x08)␊ |
42 | ␉␉␉&& (map->bios_ptr[i+7] == 0x08)) {␊ |
43 | ␉␉␉nv_modeline_2_offset = (unsigned short) i;␊ |
44 | ␉␉␉break;␊ |
45 | ␉␉}␊ |
46 | ␉␉i++;␊ |
47 | ␉}␊ |
48 | ␉␊ |
49 | ␉nv_data_table = (unsigned short *) (map->bios_ptr + (nv_data_table_offset + OFFSET_TO_VESA_TABLE_INDEX));␊ |
50 | ␉std_vesa = (NV_VESA_TABLE *) (map->bios_ptr + *nv_data_table);␊ |
51 | ␉map->mode_table = (char *) std_vesa->sModelines;␊ |
52 | ␉verbose("First Standard VESA Table at offset 0x%x\n", *nv_data_table);␊ |
53 | ␉␊ |
54 | ␉if (nv_modeline_2_offset == (VBIOS_SIZE-1) || nv_modeline_2_offset == 0) {␊ |
55 | ␉␉map->nv_mode_table_2 = NULL;␊ |
56 | ␉␉verbose("There is no Second Standard VESA Table to patch\n");␊ |
57 | ␉} else {␊ |
58 | ␉␉map->nv_mode_table_2 = (char*) map->bios_ptr + nv_modeline_2_offset;␊ |
59 | ␉␉verbose("Second Standard VESA Table at offset 0x%x\n", nv_modeline_2_offset);␊ |
60 | ␉}␊ |
61 | ␉␊ |
62 | ␉if (map->mode_table == NULL) {␊ |
63 | ␉␉verbose("Unable to locate the mode table.\n");␊ |
64 | ␉␉verbose("Please run the program 'dump_bios' as root and\n");␊ |
65 | ␉␉verbose("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n");␊ |
66 | ␉␉␊ |
67 | ␉␉close_vbios(map);␊ |
68 | ␉␉return 0;␊ |
69 | ␉}␊ |
70 | ␉␊ |
71 | ␉//This won't be used as there is no garanty this is right␊ |
72 | ␉map->mode_table_size = std_vesa->sHeader.usTable_Size;␊ |
73 | ␉␉/*␊ |
74 | ␉␉ ␉ * Determine how many modes and tables sizes␊ |
75 | ␉␉ ␉ */␊ |
76 | ␉␉␊ |
77 | ␉␉NV_MODELINE *␉mode_ptr =␉␉(NV_MODELINE *)␉␉map->mode_table;␊ |
78 | ␉␉NV_MODELINE_2 *␉mode_2_ptr =␉(NV_MODELINE_2 *)␉map->nv_mode_table_2;␊ |
79 | ␉␉map->modeline_num = map->nv_modeline_num_2 = 0;␊ |
80 | ␉␉␊ |
81 | ␉␉//First Table␊ |
82 | ␉␉while ((mode_ptr[map->modeline_num].reserved3 & 0xff) == 0xff)␊ |
83 | ␉␉␉␉map->modeline_num++;␊ |
84 | ␉␉␊ |
85 | ␉␉verbose("First VESA Table has %d modes\n",map->modeline_num);␊ |
86 | ␉␉if (map->modeline_num == 0) {␊ |
87 | ␉␉␉␉verbose("%d is incorrect, make it a 16\n",map->modeline_num);␊ |
88 | ␉␉␉␉map->modeline_num = 16;␊ |
89 | ␉␉␉}␊ |
90 | ␉␉map->mode_table_size = map->modeline_num * sizeof(NV_MODELINE);␊ |
91 | ␉␉␊ |
92 | ␉␉//Second Table␊ |
93 | ␉␉while (mode_2_ptr[map->nv_modeline_num_2].h_disp <= 0x800)␊ |
94 | ␉␉␉␉map->nv_modeline_num_2++;␊ |
95 | ␉␉␊ |
96 | ␉␉printf("Second VESA Table has %d modes\n",map->nv_modeline_num_2);␊ |
97 | ␉␉if (map->nv_modeline_num_2 == 0) {␊ |
98 | ␉␉␉␉verbose("%d is incorrect, make it a 32\n",map->nv_modeline_num_2);␊ |
99 | ␉␉␉␉map->nv_modeline_num_2 = 32;␊ |
100 | ␉␉␉}␊ |
101 | ␉␉map->nv_mode_table_2_size = map->nv_modeline_num_2 * sizeof(NV_MODELINE_2);␊ |
102 | ␉␊ |
103 | ␉return map;␊ |
104 | }␊ |
105 | ␊ |
106 | bool nvidia_set_mode(vbios_map* map, UInt8 idx, UInt32* x, UInt32* y, char Type)␊ |
107 | {␊ |
108 | ␉if (Type == MAIN_VESA_TABLE) {␊ |
109 | ␉␉NV_MODELINE * mode_timing = (NV_MODELINE *) map->mode_table;␊ |
110 | ␉␉␊ |
111 | ␉␉if ((mode_timing[idx].reserved3 & 0xff) != 0xff) return FALSE;␊ |
112 | ␉␉␊ |
113 | ␉␉if ((*x != 0) && (*y != 0) && ( mode_timing[idx].usH_Active >= 640 )) {␊ |
114 | ␉␉␉␊ |
115 | ␉␉␉verbose("Mode %dx%d -> %dx%d ", mode_timing[idx].usH_Active, mode_timing[idx].usV_Active,␊ |
116 | ␉␉␉␉␉*x, *y);␊ |
117 | ␉␉␉␊ |
118 | ␉␉␉generic_modeline modeline;␊ |
119 | ␉␉␉␊ |
120 | ␉␉␉cvt_timings(*x, *y, 60, &modeline.clock,␊ |
121 | ␉␉␉␉␉␉&modeline.hsyncstart, &modeline.hsyncend,␊ |
122 | ␉␉␉␉␉␉&modeline.htotal, &modeline.vsyncstart,␊ |
123 | ␉␉␉␉␉␉&modeline.vsyncend, &modeline.vtotal, FALSE);␊ |
124 | ␉␉␉␊ |
125 | ␉␉␉mode_timing[idx].usH_Active = *x;␊ |
126 | ␉␉␉mode_timing[idx].usH_Active_minus_One = *x - 1;␊ |
127 | ␉␉␉mode_timing[idx].usH_Active_minus_One_ = *x - 1;␊ |
128 | ␉␉␉␊ |
129 | ␉␉␉mode_timing[idx].usV_Active = *y;␊ |
130 | ␉␉␉mode_timing[idx].usV_Active_minus_One = *y - 1;␊ |
131 | ␉␉␉mode_timing[idx].usV_Active_minus_One_ = *y - 1;␊ |
132 | ␉␉␉␊ |
133 | ␉␉␉mode_timing[idx].usH_Total = modeline.htotal;␊ |
134 | ␉␉␉mode_timing[idx].usH_SyncStart = modeline.hsyncstart;␊ |
135 | ␉␉␉mode_timing[idx].usH_SyncEnd = modeline.hsyncend;␊ |
136 | ␉␉␉␊ |
137 | ␉␉␉mode_timing[idx].usV_Total = modeline.vtotal;␊ |
138 | ␉␉␉mode_timing[idx].usV_SyncStart = modeline.vsyncstart;␊ |
139 | ␉␉␉mode_timing[idx].usV_SyncEnd = modeline.vsyncend;␊ |
140 | ␉␉␉␊ |
141 | ␉␉␉mode_timing[idx].usPixel_Clock = modeline.clock;␊ |
142 | ␉␉}␊ |
143 | ␉␉␊ |
144 | ␉␉*x = mode_timing[idx + 1].usH_Active;␊ |
145 | ␉␉*y = mode_timing[idx + 1].usV_Active;␊ |
146 | ␉}␊ |
147 | ␉␊ |
148 | ␉if (Type == SECOND_VESA_TABLE) {␊ |
149 | ␉␉NV_MODELINE_2 * mode_timing = (NV_MODELINE_2 *) map->nv_mode_table_2;␊ |
150 | ␉␉␊ |
151 | ␉␉if (mode_timing[idx].h_disp > 0x800) return FALSE;␊ |
152 | ␉␉␊ |
153 | ␉␉if ((*x != 0) && (*y != 0) && ( mode_timing[idx].h_disp >= 640 )) {␊ |
154 | ␉␉␉␊ |
155 | ␉␉␉verbose("Mode %dx%d -> %dx%d ", mode_timing[idx].h_disp, mode_timing[idx].v_disp,␊ |
156 | ␉␉␉␉␉*x, *y);␊ |
157 | ␉␉␉␊ |
158 | ␉␉␉generic_modeline modeline;␊ |
159 | ␉␉␉␊ |
160 | ␉␉␉cvt_timings(*x, *y, 60, &modeline.clock,␊ |
161 | ␉␉␉␉␉␉&modeline.hsyncstart, &modeline.hsyncend,␊ |
162 | ␉␉␉␉␉␉&modeline.htotal, &modeline.vsyncstart,␊ |
163 | ␉␉␉␉␉␉&modeline.vsyncend, &modeline.vtotal, TRUE);␊ |
164 | ␉␉␉␊ |
165 | ␉␉␉mode_timing[idx].h_disp = *x;␊ |
166 | ␉␉␉mode_timing[idx].v_disp = *y;␊ |
167 | ␉␉␉mode_timing[idx].h_blank = modeline.htotal - *x;␊ |
168 | ␉␉␉mode_timing[idx].h_syncoffset = modeline.hsyncstart - *x;␊ |
169 | ␉␉␉mode_timing[idx].h_syncwidth = modeline.hsyncend - modeline.hsyncstart;␊ |
170 | ␉␉␉mode_timing[idx].v_blank = modeline.vtotal - *y;␊ |
171 | ␉␉}␊ |
172 | ␉␉␊ |
173 | ␉␉*x = mode_timing[idx + 1].h_disp;␊ |
174 | ␉␉*y = mode_timing[idx + 1].v_disp;␊ |
175 | ␉}␊ |
176 | ␉return TRUE;␊ |
177 | }␊ |
178 | |