1 | /*␊ |
2 | * gma_resolution.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 * bios_type_names[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};␊ |
13 | int freqs[] = { 60, 75, 85 };␊ |
14 | ␊ |
15 | ␊ |
16 | vbios_resolution_type1 * map_type1_resolution(vbios_map * map, UInt16 res) {␊ |
17 | ␉vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res)); ␊ |
18 | ␉return ptr;␊ |
19 | }␊ |
20 | ␊ |
21 | vbios_resolution_type2 * map_type2_resolution(vbios_map * map, UInt16 res) {␊ |
22 | ␉vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res)); ␊ |
23 | ␉return ptr;␊ |
24 | }␊ |
25 | ␊ |
26 | vbios_resolution_type3 * map_type3_resolution(vbios_map * map, UInt16 res) {␊ |
27 | ␉vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res)); ␊ |
28 | ␉return ptr;␊ |
29 | }␊ |
30 | ␊ |
31 | char detect_bios_type(vbios_map * map, char modeline, int entry_size) {␊ |
32 | ␉UInt32 i;␊ |
33 | ␉UInt16 r1, r2;␊ |
34 | ␉␊ |
35 | ␉vbios_mode * mode_table = (vbios_mode *)map->mode_table;␊ |
36 | ␉␊ |
37 | ␉r1 = r2 = 32000;␊ |
38 | ␉␊ |
39 | ␉for (i=0; i < map->mode_table_size; i++) {␊ |
40 | ␉␉if (mode_table[i].resolution <= r1) {␊ |
41 | ␉␉␉r1 = mode_table[i].resolution;␊ |
42 | ␉␉}␊ |
43 | ␉␉else {␊ |
44 | ␉␉␉if (mode_table[i].resolution <= r2) {␊ |
45 | ␉␉␉␉r2 = mode_table[i].resolution;␊ |
46 | ␉␉␉}␊ |
47 | ␉␉}␊ |
48 | ␉␉␊ |
49 | ␉␉/*PRINT("r1 = %d r2 = %d\n", r1, r2);*/␊ |
50 | ␉}␊ |
51 | ␉␊ |
52 | ␉return (r2-r1-6) % entry_size == 0;␊ |
53 | }␊ |
54 | ␊ |
55 | vbios_map * open_intel_vbios(vbios_map *map)␊ |
56 | {␊ |
57 | ␉/*␊ |
58 | ␉ * Find the location of the Mode Table␊ |
59 | ␉ */␊ |
60 | ␉unsigned char* p = map->bios_ptr + 16;␊ |
61 | ␉unsigned char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));␊ |
62 | ␉␊ |
63 | ␉while (p < limit && map->mode_table == 0) {␊ |
64 | ␉␉vbios_mode* mode_ptr = (vbios_mode*) p;␊ |
65 | ␉␉␊ |
66 | ␉␉if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&␊ |
67 | ␉␉␉((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {␊ |
68 | ␉␉␉␊ |
69 | ␉␉␉map->mode_table = (char *)mode_ptr;␊ |
70 | ␉␉}␊ |
71 | ␉␉␊ |
72 | ␉␉p++;␊ |
73 | ␉}␊ |
74 | ␉␊ |
75 | ␉if (map->mode_table == 0) {␊ |
76 | ␉␉PRINT("Unable to locate the mode table.\n");␊ |
77 | ␉␉PRINT("Please run the program 'dump_bios' as root and\n");␊ |
78 | ␉␉PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n");␊ |
79 | ␉␉␊ |
80 | ␉␉close_vbios(map);␊ |
81 | ␉␉return 0;␊ |
82 | ␉}␊ |
83 | ␉␊ |
84 | ␉PRINT("Mode Table at offset : 0x%x\n", ((unsigned char *)map->mode_table) - map->bios_ptr);␊ |
85 | ␉␊ |
86 | ␉/*␊ |
87 | ␉ * Determine size of mode table␊ |
88 | ␉ */␊ |
89 | ␉␊ |
90 | ␉vbios_mode * mode_ptr = (vbios_mode *)map->mode_table;␊ |
91 | ␉␊ |
92 | ␉while (mode_ptr->mode != 0xff) {␊ |
93 | ␉␉map->mode_table_size++;␊ |
94 | ␉␉mode_ptr++;␊ |
95 | ␉}␊ |
96 | ␉␊ |
97 | ␉map->modeline_num = map->mode_table_size;␊ |
98 | ␉PRINT("Mode Table size : %d\n", map->modeline_num);␊ |
99 | ␉␊ |
100 | ␉/*␊ |
101 | ␉ * Figure out what type of bios we have␊ |
102 | ␉ * order of detection is important␊ |
103 | ␉ */␊ |
104 | ␉␊ |
105 | ␉if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3))) {␊ |
106 | ␉␉map->bios = BT_3;␊ |
107 | ␉␉PRINT("Bios Type : BT_3\n");␊ |
108 | ␉}␊ |
109 | ␉else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2))) {␊ |
110 | ␉␉map->bios = BT_2;␊ |
111 | ␉␉PRINT("Bios Type : BT_2\n");␊ |
112 | ␉}␊ |
113 | ␉else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1))) {␊ |
114 | ␉␉map->bios = BT_1;␊ |
115 | ␉␉PRINT("Bios Type : BT_1\n");␊ |
116 | ␉}␊ |
117 | ␉else {␊ |
118 | ␉␉PRINT("Unable to determine bios type.\n");␊ |
119 | ␉␉PRINT("Please run the program 'dump_bios' as root and\n");␊ |
120 | ␉␉PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n");␊ |
121 | ␉␉␊ |
122 | ␉␉return 0;␊ |
123 | ␉}␊ |
124 | ␉␊ |
125 | ␉return map;␊ |
126 | }␊ |
127 | ␉␊ |
128 | ␊ |
129 | ␊ |
130 | bool intel_set_mode_1(vbios_map* map, UInt8 idx, UInt32* x, UInt32* y)␊ |
131 | {␊ |
132 | ␉vbios_mode *mode_timing = (vbios_mode *) map->mode_table;␊ |
133 | ␉vbios_resolution_type1 * res = map_type1_resolution(map, mode_timing[idx].resolution);␊ |
134 | ␉␊ |
135 | ␉UInt32 actual_x = ((res->x2 & 0xf0) << 4) | (res->x1 & 0xff);␊ |
136 | ␉UInt32 actual_y = ((res->y2 & 0xf0) << 4) | (res->y1 & 0xff);␊ |
137 | ␉␊ |
138 | ␉if ((*x != 0) && (*y != 0) && ( actual_x >= 640 )) {␊ |
139 | ␉␉␊ |
140 | ␉␉PRINT("Mode %dx%d -> %dx%d \n", actual_x, actual_y, *x, *y);␊ |
141 | ␉␉␊ |
142 | ␉␉res->x2 = (res->x2 & 0x0f) | ((*x >> 4) & 0xf0);␊ |
143 | ␉␉res->x1 = (*x & 0xff);␊ |
144 | ␉␉␊ |
145 | ␉␉res->y2 = ((*y >> 4) & 0xf0);␊ |
146 | ␉␉res->y1 = (*y & 0xff);␊ |
147 | ␉}␊ |
148 | ␉␊ |
149 | ␉res = map_type1_resolution(map, mode_timing[idx + 1].resolution);␊ |
150 | ␉␊ |
151 | ␉actual_x = ((res->x2 & 0xf0) << 4) | (res->x1 & 0xff);␊ |
152 | ␉actual_y = ((res->y2 & 0xf0) << 4) | (res->y1 & 0xff);␊ |
153 | ␉␊ |
154 | ␉*x = actual_x;␊ |
155 | ␉*y = actual_y;␊ |
156 | ␉␊ |
157 | ␉return TRUE;␊ |
158 | }␊ |
159 | ␊ |
160 | bool intel_set_mode_2(vbios_map* map, UInt8 idx, UInt32* x, UInt32* y)␊ |
161 | {␊ |
162 | ␉UInt32 xprev, yprev, j = 0;␊ |
163 | ␉␊ |
164 | ␉vbios_mode *mode_timing = (vbios_mode *) map->mode_table;␊ |
165 | ␉vbios_resolution_type2 * res = map_type2_resolution(map, mode_timing[idx].resolution);␊ |
166 | ␉␊ |
167 | ␉if ((*x != 0) && (*y != 0) && ((res->modelines[0].x1 + 1) >= 640 )) {␊ |
168 | ␉␉␊ |
169 | ␉␉PRINT("Mode %dx%d -> %dx%d \n", res->modelines[0].x1 + 1, res->modelines[0].y1 + 1, *x, *y);␊ |
170 | ␉␉␊ |
171 | ␉␉res->xchars = *x / 8;␊ |
172 | ␉␉res->ychars = *y / 16 - 1;␊ |
173 | ␉␉xprev = res->modelines[0].x1;␊ |
174 | ␉␉yprev = res->modelines[0].y1;␊ |
175 | ␉␉␊ |
176 | ␉␉for(j = 0; j < 3; j++) {␊ |
177 | ␉␉␉vbios_modeline_type2 * mode = &res->modelines[j];␊ |
178 | ␉␉␉␊ |
179 | ␉␉␉if (mode->x1 == xprev && mode->y1 == yprev) {␊ |
180 | ␉␉␉␉mode->x1 = mode->x2 = *x-1;␊ |
181 | ␉␉␉␉mode->y1 = mode->y2 = *y-1;␊ |
182 | ␉␉␉␉␊ |
183 | ␉␉␉␉gtf_timings(*x, *y, freqs[j], &mode->clock,␊ |
184 | ␉␉␉␉␉␉␉&mode->hsyncstart, &mode->hsyncend,␊ |
185 | ␉␉␉␉␉␉␉&mode->hblank, &mode->vsyncstart,␊ |
186 | ␉␉␉␉␉␉␉&mode->vsyncend, &mode->vblank);␊ |
187 | ␉␉␉␉␊ |
188 | ␉␉␉␉mode->htotal = mode->hblank;␊ |
189 | ␉␉␉␉mode->vtotal = mode->vblank;␊ |
190 | ␉␉␉}␊ |
191 | ␉␉}␊ |
192 | ␉}␊ |
193 | ␉␊ |
194 | ␉res = map_type2_resolution(map, mode_timing[idx + 1].resolution);␊ |
195 | ␉␊ |
196 | ␉*x = res->modelines[0].x1 + 1;␊ |
197 | ␉*y = res->modelines[0].y1 + 1;␊ |
198 | ␉␊ |
199 | ␉return TRUE;␊ |
200 | }␊ |
201 | ␊ |
202 | bool intel_set_mode_3(vbios_map* map, UInt8 idx, UInt32* x, UInt32* y)␊ |
203 | {␊ |
204 | ␉UInt32 xprev, yprev, j = 0;␊ |
205 | ␉␊ |
206 | ␉vbios_mode *mode_timing = (vbios_mode *) map->mode_table;␊ |
207 | ␉vbios_resolution_type3 * res = map_type3_resolution(map, mode_timing[idx].resolution);␊ |
208 | ␉␊ |
209 | ␉if ((*x != 0) && (*y != 0) && ((res->modelines[0].x1 + 1) >= 640 )) {␊ |
210 | ␉␉␊ |
211 | ␉␉PRINT("Mode %dx%d -> %dx%d \n", res->modelines[0].x1 + 1, res->modelines[0].y1 + 1, *x, *y);␊ |
212 | ␉␉␊ |
213 | ␉␉xprev = res->modelines[0].x1;␊ |
214 | ␉␉yprev = res->modelines[0].y1;␊ |
215 | ␉␉␊ |
216 | ␉␉for(j = 0; j < 3; j++) {␊ |
217 | ␉␉␉vbios_modeline_type3 * mode = &res->modelines[j];␊ |
218 | ␉␉␉␊ |
219 | ␉␉␉if (mode->x1 == xprev && mode->y1 == yprev) {␊ |
220 | ␉␉␉␉mode->x1 = mode->x2 = *x-1;␊ |
221 | ␉␉␉␉mode->y1 = mode->y2 = *y-1;␊ |
222 | ␉␉␉␉␊ |
223 | ␉␉␉␉gtf_timings(*x, *y, freqs[j], &mode->clock,␊ |
224 | ␉␉␉␉␉␉␉&mode->hsyncstart, &mode->hsyncend,␊ |
225 | ␉␉␉␉␉␉␉&mode->hblank, &mode->vsyncstart,␊ |
226 | ␉␉␉␉␉␉␉&mode->vsyncend, &mode->vblank);␊ |
227 | ␉␉␉␉␊ |
228 | ␉␉␉␉mode->htotal = mode->hblank;␊ |
229 | ␉␉␉␉mode->vtotal = mode->vblank;␊ |
230 | ␉␉␉␉␊ |
231 | ␉␉␉␉mode->timing_h = *y-1;␊ |
232 | ␉␉␉␉mode->timing_v = *x-1;␊ |
233 | ␉␉␉}␊ |
234 | ␉␉}␊ |
235 | ␉}␊ |
236 | ␉res = map_type3_resolution(map, mode_timing[idx + 1].resolution);␊ |
237 | ␉␊ |
238 | ␉*x = res->modelines[0].x1 + 1;␊ |
239 | ␉*y = res->modelines[0].y1 + 1;␊ |
240 | ␉␊ |
241 | ␉return TRUE;␊ |
242 | } |