1 | /*␊ |
2 | * gmaResolution.c␊ |
3 | * ␊ |
4 | *␊ |
5 | * Created by Le Bidou on 19/03/10.␊ |
6 | * Copyright 2010 ---. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include "gma_resolution.h"␊ |
11 | ␊ |
12 | char * biosTypeNames[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};␊ |
13 | int freqs[] = { 60, 75, 85 };␊ |
14 | ␊ |
15 | ␊ |
16 | vbiosResolutionType1 * mapType1Resolution(vBiosMap * map, uint16_t res)␊ |
17 | {␊ |
18 | ␉vbiosResolutionType1 * ptr = ((vbiosResolutionType1*)(map->biosPtr + res)); ␊ |
19 | ␉return ptr;␊ |
20 | }␊ |
21 | ␊ |
22 | vbiosResolutionType2 * mapType2Resolution(vBiosMap * map, uint16_t res)␊ |
23 | {␊ |
24 | ␉vbiosResolutionType2 * ptr = ((vbiosResolutionType2*)(map->biosPtr + res)); ␊ |
25 | ␉return ptr;␊ |
26 | }␊ |
27 | ␊ |
28 | vbiosResolutionType3 * mapType3Resolution(vBiosMap * map, uint16_t res)␊ |
29 | {␊ |
30 | ␉vbiosResolutionType3 * ptr = ((vbiosResolutionType3*)(map->biosPtr + res)); ␊ |
31 | ␉return ptr;␊ |
32 | }␊ |
33 | ␊ |
34 | char detectBiosType(vBiosMap * map, char modeline, int entrySize)␊ |
35 | {␊ |
36 | ␉uint32_t i;␊ |
37 | ␉uint16_t r1, r2;␊ |
38 | ␉␊ |
39 | ␉vbiosMode * modeTable = (vbiosMode *)map->modeTables->pointer;␊ |
40 | ␉␊ |
41 | ␉r1 = r2 = 32000;␊ |
42 | ␉␊ |
43 | ␉for (i=0; i < map->modeTables->size; i++)␊ |
44 | ␉{␊ |
45 | ␉␉if (modeTable[i].resolution <= r1)␊ |
46 | ␉␉␉r1 = modeTable[i].resolution;␊ |
47 | ␉␉else if (modeTable[i].resolution <= r2)␊ |
48 | ␉␉␉r2 = modeTable[i].resolution;␊ |
49 | ␉}␊ |
50 | ␉␊ |
51 | ␉return (r2-r1-6) % entrySize == 0;␊ |
52 | }␊ |
53 | ␊ |
54 | vBiosMap * openIntelVbios(vBiosMap *map)␊ |
55 | {␊ |
56 | ␉/*␊ |
57 | ␉ * Find the location of the Mode Table␊ |
58 | ␉ */␊ |
59 | ␉unsigned char* p = map->biosPtr + 16;␊ |
60 | ␉unsigned char* limit = map->biosPtr + VBIOS_SIZE - (3 * sizeof(vbiosMode));␊ |
61 | ␉␊ |
62 | ␉// initialize the table chain with one element␊ |
63 | ␉sModeTable * table = intializeTables(map, 1);␊ |
64 | ␉␊ |
65 | ␉while (p < limit && table->pointer == 0)␊ |
66 | ␉{␊ |
67 | ␉␉vbiosMode* modePtr = (vbiosMode*) p;␊ |
68 | ␉␉␊ |
69 | ␉␉if (((modePtr[0].mode & 0xf0) == 0x30) && ((modePtr[1].mode & 0xf0) == 0x30) &&␊ |
70 | ␉␉␉((modePtr[2].mode & 0xf0) == 0x30) && ((modePtr[3].mode & 0xf0) == 0x30))␊ |
71 | ␉␉{␊ |
72 | ␉␉␉␊ |
73 | ␉␉␉table->pointer = (uint8_t *)modePtr;␊ |
74 | ␉␉}␊ |
75 | ␉␉␊ |
76 | ␉␉p++;␊ |
77 | ␉}␊ |
78 | ␉␊ |
79 | ␉if (table->pointer == 0)␊ |
80 | ␉{␊ |
81 | ␉␉PRINT("Unable to locate the mode table.\n");␊ |
82 | ␉␉PRINT("Please run the program 'dump_bios' as root and\n");␊ |
83 | ␉␉PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n");␊ |
84 | ␉␉␊ |
85 | ␉␉closeVbios(map);␊ |
86 | ␉␉return 0;␊ |
87 | ␉}␊ |
88 | ␉␊ |
89 | ␉PRINT("Mode Table at offset: 0x%x\n", (table->pointer) - map->biosPtr);␊ |
90 | ␉␊ |
91 | ␉/*␊ |
92 | ␉ * Determine size of mode table␊ |
93 | ␉ */␊ |
94 | ␉␊ |
95 | ␉vbiosMode * modePtr = (vbiosMode *)table->pointer;␊ |
96 | ␉␊ |
97 | ␉while (modePtr->mode != 0xff)␊ |
98 | ␉{␊ |
99 | ␉␉table->size++;␊ |
100 | ␉␉modePtr++;␊ |
101 | ␉}␊ |
102 | ␉␊ |
103 | ␉table->modeCount = table->size;␊ |
104 | ␉PRINT("Mode Table size: %d\n", table->modeCount);␊ |
105 | ␉␊ |
106 | ␉/*␊ |
107 | ␉ * Figure out what type of bios we have␊ |
108 | ␉ * order of detection is important␊ |
109 | ␉ */␊ |
110 | ␉␊ |
111 | ␉if (detectBiosType(map, true, sizeof(vbiosModelineType3)))␊ |
112 | ␉{␊ |
113 | ␉␉map->bios = BT_3;␊ |
114 | ␉␉map->setMode = intelSetMode_3;␊ |
115 | ␉␉PRINT("Bios Type: BT_3\n");␊ |
116 | ␉}␊ |
117 | ␉else if (detectBiosType(map, true, sizeof(vbiosModelineType2)))␊ |
118 | ␉{␊ |
119 | ␉␉map->bios = BT_2;␊ |
120 | ␉␉map->setMode = intelSetMode_2;␊ |
121 | ␉␉PRINT("Bios Type: BT_2\n");␊ |
122 | ␉}␊ |
123 | ␉else if (detectBiosType(map, false, sizeof(vbiosResolutionType1)))␊ |
124 | ␉{␊ |
125 | ␉␉map->bios = BT_1;␊ |
126 | ␉␉map->setMode = intelSetMode_1;␊ |
127 | ␉␉PRINT("Bios Type: BT_1\n");␊ |
128 | ␉}␊ |
129 | ␉else␊ |
130 | ␉{␊ |
131 | ␉␉PRINT("Unable to determine bios type.\n");␊ |
132 | ␉␉PRINT("Please run the program 'dump_bios' as root and\n");␊ |
133 | ␉␉PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n"); //Azi: remove?␊ |
134 | ␉␉␊ |
135 | ␉␉return 0;␊ |
136 | ␉}␊ |
137 | ␉␊ |
138 | ␉return map;␊ |
139 | }␊ |
140 | ␉␊ |
141 | ␊ |
142 | ␊ |
143 | bool intelSetMode_1(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y)␊ |
144 | {␊ |
145 | ␉vbiosMode *modeTiming = (vbiosMode *) table->pointer;␊ |
146 | ␉vbiosResolutionType1 * res = mapType1Resolution(map, modeTiming[idx].resolution);␊ |
147 | ␉␊ |
148 | ␉//retreive the original mode's dimensions␊ |
149 | ␉uint32_t actualX = ((res->hActive2 & 0xf0) << 4) | (res->hActive1 & 0xff);␊ |
150 | ␉uint32_t actualY = ((res->vActive2 & 0xf0) << 4) | (res->vActive1 & 0xff);␊ |
151 | ␉␊ |
152 | ␉// patch only if mode differs␊ |
153 | ␉if ((*x != actualX) || (*y != actualY))␊ |
154 | ␉{␉␊ |
155 | ␉␉PRINT("Mode %dx%d -> ", actualX, actualY);␊ |
156 | ␉␉␊ |
157 | ␉␉res->hActive2 = (res->hActive2 & 0x0f) | ((*x >> 4) & 0xf0);␊ |
158 | ␉␉res->hActive1 = (*x & 0xff);␊ |
159 | ␉␉␊ |
160 | ␉␉res->vActive2 = (res->hActive2 & 0x0f) | ((*y >> 4) & 0xf0);␊ |
161 | ␉␉res->vActive1 = (*y & 0xff);␊ |
162 | ␉␉␊ |
163 | ␉␉uint32_t actualX = ((res->hActive2 & 0xf0) << 4) | (res->hActive1 & 0xff);␊ |
164 | ␉␉uint32_t actualY = ((res->vActive2 & 0xf0) << 4) | (res->vActive1 & 0xff);␊ |
165 | ␉␉␊ |
166 | ␉␉PRINT("%dx%d \n", actualX, actualY);␊ |
167 | ␉}␊ |
168 | ␉␊ |
169 | ␉//since only the first mode is patched, this is deprecated␊ |
170 | ␉res = mapType1Resolution(map, modeTiming[idx + 1].resolution);␊ |
171 | ␉␊ |
172 | ␉actualX = ((res->hActive2 & 0xf0) << 4) | (res->hActive1 & 0xff);␊ |
173 | ␉actualY = ((res->vActive2 & 0xf0) << 4) | (res->vActive1 & 0xff);␊ |
174 | ␉␊ |
175 | ␉*x = actualX;␊ |
176 | ␉*y = actualY;␊ |
177 | ␉␊ |
178 | ␉return true;␊ |
179 | }␊ |
180 | ␊ |
181 | bool intelSetMode_2(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y)␊ |
182 | {␊ |
183 | ␉uint32_t xprev, yprev, j = 0;␊ |
184 | ␉␊ |
185 | ␉vbiosMode *modeTiming = (vbiosMode *) table->pointer;␊ |
186 | ␉vbiosResolutionType2 * res = mapType2Resolution(map, modeTiming[idx].resolution);␊ |
187 | ␉␊ |
188 | ␉//patch only if mode differs␊ |
189 | ␉if (␉(*x != (res->modelines[0].hActive1 + 1)) ␊ |
190 | ␉␉||␉(*y != (res->modelines[0].vActive1 + 1)) )␊ |
191 | ␉{␊ |
192 | ␉␉␊ |
193 | ␉␉PRINT("Mode %dx%d -> ", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1);␊ |
194 | ␉␉␊ |
195 | ␉␉res->xChars = *x / 8;␊ |
196 | ␉␉res->yChars = *y / 16 - 1;␊ |
197 | ␉␉xprev = res->modelines[0].hActive1;␊ |
198 | ␉␉yprev = res->modelines[0].vActive1;␊ |
199 | ␉␉␊ |
200 | ␉␉// recalculate timigs for all frequencies and patch␊ |
201 | ␉␉for(j = 0; j < 3; j++)␊ |
202 | ␉␉{␊ |
203 | ␉␉␉vbiosModelineType2 * mode = &res->modelines[j];␊ |
204 | ␉␉␉␊ |
205 | ␉␉␉if (mode->hActive1 == xprev && mode->vActive1 == yprev)␊ |
206 | ␉␉␉{␊ |
207 | ␉␉␉␉mode->hActive1 = mode->hActive2 = *x - 1;␊ |
208 | ␉␉␉␉mode->vActive1 = mode->vActive2 = *y - 1;␊ |
209 | ␉␉␉␉␊ |
210 | ␉␉␉␉gtfTimings(*x, *y, freqs[j], &mode->clock,␊ |
211 | ␉␉␉␉␉␉␉&mode->hSyncStart, &mode->hSyncEnd,␊ |
212 | ␉␉␉␉␉␉␉&mode->hBlank, &mode->vSyncStart,␊ |
213 | ␉␉␉␉␉␉␉&mode->vSyncEnd, &mode->vBlank);␊ |
214 | ␉␉␉␉␊ |
215 | ␉␉␉␉mode->hTotal = mode->hBlank;␊ |
216 | ␉␉␉␉mode->vTotal = mode->vBlank;␊ |
217 | ␉␉␉}␊ |
218 | ␉␉}␊ |
219 | ␉␉PRINT("%dx%d\n", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1);␊ |
220 | ␉␉␊ |
221 | ␉}␊ |
222 | ␉//since only the first mode is patched, this is deprecated␊ |
223 | ␉res = mapType2Resolution(map, modeTiming[idx + 1].resolution);␊ |
224 | ␉␊ |
225 | ␉*x = res->modelines[0].hActive1 + 1;␊ |
226 | ␉*y = res->modelines[0].vActive1 + 1;␊ |
227 | ␉␊ |
228 | ␉return true;␊ |
229 | }␊ |
230 | ␊ |
231 | bool intelSetMode_3(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y)␊ |
232 | {␊ |
233 | ␉uint32_t xprev, yprev, j = 0;␊ |
234 | ␉␊ |
235 | ␉vbiosMode *modeTiming = (vbiosMode *) table->pointer;␊ |
236 | ␉vbiosResolutionType3 * res = mapType3Resolution(map, modeTiming[idx].resolution);␊ |
237 | ␉␊ |
238 | ␉// patch only if mode differs␊ |
239 | ␉if (␉(*x != (res->modelines[0].hActive1 + 1)) ␊ |
240 | ␉␉||␉(*y != (res->modelines[0].vActive1 + 1)) )␊ |
241 | ␉{␊ |
242 | ␉␉␊ |
243 | ␉␉PRINT("Mode %dx%d -> ", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1);␊ |
244 | ␉␉␊ |
245 | ␉␉xprev = res->modelines[0].hActive1;␊ |
246 | ␉␉yprev = res->modelines[0].vActive1;␊ |
247 | ␉␉␊ |
248 | ␉␉// recalculate timings for all frequencies and patch␊ |
249 | ␉␉for(j = 0; j < 3; j++) {␊ |
250 | ␉␉␉vbiosModelineType3 * mode = &res->modelines[j];␊ |
251 | ␉␉␉␊ |
252 | ␉␉␉if (mode->hActive1 == xprev && mode->vActive1 == yprev)␊ |
253 | ␉␉␉{␊ |
254 | ␉␉␉␉mode->hActive1 = mode->hActive2 = *x - 1;␊ |
255 | ␉␉␉␉mode->vActive1 = mode->vActive2 = *y - 1;␊ |
256 | ␉␉␉␉␊ |
257 | ␉␉␉␉gtfTimings(*x, *y, freqs[j], &mode->clock,␊ |
258 | ␉␉␉␉␉␉␉&mode->hSyncStart, &mode->hSyncEnd,␊ |
259 | ␉␉␉␉␉␉␉&mode->hBlank, &mode->vSyncStart,␊ |
260 | ␉␉␉␉␉␉␉&mode->vSyncEnd, &mode->vBlank);␊ |
261 | ␉␉␉␉␊ |
262 | ␉␉␉␉mode->hTotal = mode->hBlank;␊ |
263 | ␉␉␉␉mode->vTotal = mode->vBlank;␊ |
264 | ␉␉␉␉␊ |
265 | ␉␉␉␉mode->timingH = *y-1;␊ |
266 | ␉␉␉␉mode->timingV = *x-1;␊ |
267 | ␉␉␉}␊ |
268 | ␉␉}␊ |
269 | ␉␉␊ |
270 | ␉␉PRINT("%dx%d\n", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1);␊ |
271 | ␉␉␊ |
272 | ␉}␊ |
273 | ␉//since only the first mode is patched, this is deprecated␊ |
274 | ␉res = mapType3Resolution(map, modeTiming[idx + 1].resolution);␊ |
275 | ␉␊ |
276 | ␉*x = res->modelines[0].hActive1 + 1;␊ |
277 | ␉*y = res->modelines[0].vActive1 + 1;␊ |
278 | ␉␊ |
279 | ␉return true;␊ |
280 | } |