Chameleon

Chameleon Svn Source Tree

Root/branches/valv/i386/libsaio/915resolution.c

1
2/* Copied from 915 resolution created by steve tomljenovic
3 *
4 * This code is based on the techniques used in :
5 *
6 * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
7 * for demonstrating how to shadow the VBIOS into system RAM
8 * and then modify it.
9 *
10 * - 1280patch by Andrew Tipton (andrewtipton null li).
11 *
12 * - 855resolution by Alain Poirier
13 *
14 * This source code is into the public domain.
15 */
16
17#include "libsaio.h"
18#include "915resolution.h"
19
20char * chipset_type_names[] = {
21"UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME",
22"946GZ", "G965", "Q965", "965GM", "500"
23};
24
25char * bios_type_names[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};
26
27int freqs[] = { 60, 75, 85 };
28
29UInt32 get_chipset_id(void) {
30outl(0xcf8, 0x80000000);
31return inl(0xcfc);
32}
33
34chipset_type get_chipset(UInt32 id) {
35chipset_type type;
36
37switch (id) {
38case 0x35758086:
39type = CT_830;
40break;
41
42case 0x25608086:
43type = CT_845G;
44break;
45
46case 0x35808086:
47type = CT_855GM;
48break;
49
50case 0x25708086:
51type = CT_865G;
52break;
53
54case 0x25808086:
55type = CT_915G;
56break;
57
58case 0x25908086:
59type = CT_915GM;
60break;
61
62case 0x27708086:
63type = CT_945G;
64break;
65
66case 0x27a08086:
67type = CT_945GM;
68break;
69
70case 0x27a68086:
71type = CT_945GM;
72break;
73
74case 0x27ac8086:
75type = CT_945GME;
76break;
77
78case 0x27ae8086:
79type = CT_945GM;
80break;
81
82case 0x29708086:
83type = CT_946GZ;
84break;
85
86case 0x29a08086:
87type = CT_G965;
88break;
89
90case 0x29908086:
91type = CT_Q965;
92break;
93
94case 0x81008086:
95type = CT_500;
96break;
97
98case 0x2a008086:
99type = CT_965GM;
100break;
101
102
103default:
104type = CT_UNKWN;
105break;
106}
107return type;
108}
109
110vbios_resolution_type1 * map_type1_resolution(vbios_map * map, UInt16 res) {
111vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res));
112return ptr;
113}
114
115vbios_resolution_type2 * map_type2_resolution(vbios_map * map, UInt16 res) {
116vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res));
117return ptr;
118}
119
120vbios_resolution_type3 * map_type3_resolution(vbios_map * map, UInt16 res) {
121vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res));
122return ptr;
123}
124
125char detect_bios_type(vbios_map * map, char modeline, int entry_size) {
126UInt32 i;
127UInt16 r1, r2;
128
129r1 = r2 = 32000;
130
131for (i=0; i < map->mode_table_size; i++) {
132if (map->mode_table[i].resolution <= r1) {
133r1 = map->mode_table[i].resolution;
134}
135else {
136if (map->mode_table[i].resolution <= r2) {
137r2 = map->mode_table[i].resolution;
138}
139}
140
141/*printf("r1 = %d r2 = %d\n", r1, r2);*/
142}
143
144return (r2-r1-6) % entry_size == 0;
145}
146
147void close_vbios(vbios_map * map);
148
149vbios_map * open_vbios(chipset_type forced_chipset) {
150UInt32 z;
151vbios_map * map = NEW(vbios_map);
152for(z=0; z<sizeof(vbios_map); z++) ((char*)map)[z]=0;
153/*
154 * Determine chipset
155 + */
156
157if (forced_chipset == CT_UNKWN) {
158map->chipset_id = get_chipset_id();
159map->chipset = get_chipset(map->chipset_id);
160}
161else if (forced_chipset != CT_UNKWN) {
162map->chipset = forced_chipset;
163}
164else {
165map->chipset = CT_915GM;
166}
167
168/*
169 * Map the video bios to memory
170 */
171
172map->bios_ptr=(char*)VBIOS_START;
173
174/*
175 * check if we have ATI Radeon
176 */
177
178/*if (memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE1, strlen(ATI_SIGNATURE1)) ||
179memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE2, strlen(ATI_SIGNATURE2)) ) {
180printf(stderr, "ATI chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\n");
181return 0;
182}*/
183
184/*
185 * check if we have NVIDIA
186 */
187
188/*if (memmem(map->bios_ptr, VBIOS_SIZE, NVIDIA_SIGNATURE, strlen(NVIDIA_SIGNATURE))) {
189printf("NVIDIA chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\n");
190return 0;
191}*/
192
193/*
194 * check if we have Intel
195 */
196
197/*if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) {
198printf( "Intel chipset detected. However, 915resolution was unable to determine the chipset type.\n");
199
200printf("Chipset Id: %x\n", map->chipset_id);
201
202printf("Please report this problem to stomljen@yahoo.com\n");
203
204close_vbios(map);
205return 0;
206}*/
207
208/*
209 * check for others
210 */
211
212if (map->chipset == CT_UNKWN) {
213printf("Unknown chipset type and unrecognized bios.\n");
214
215printf("915resolution only works with Intel 800/900 series graphic chipsets.\n");
216
217printf("Chipset Id: %x\n", map->chipset_id);
218close_vbios(map);
219return 0;
220}
221
222/*
223 * Figure out where the mode table is
224 */
225
226{
227char* p = map->bios_ptr + 16;
228char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));
229
230while (p < limit && map->mode_table == 0) {
231vbios_mode * mode_ptr = (vbios_mode *) p;
232
233if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&
234((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {
235
236map->mode_table = mode_ptr;
237}
238
239p++;
240}
241
242if (map->mode_table == 0) {
243printf("Unable to locate the mode table.\n");
244printf("Please run the program 'dump_bios' as root and\n");
245printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");
246printf("Chipset: %s\n", chipset_type_names[map->chipset]);
247close_vbios(map);
248return 0;
249}
250}
251
252/*
253 * Determine size of mode table
254 */
255
256{
257vbios_mode * mode_ptr = map->mode_table;
258
259while (mode_ptr->mode != 0xff) {
260map->mode_table_size++;
261mode_ptr++;
262}
263}
264
265/*
266 * Figure out what type of bios we have
267 * order of detection is important
268 */
269
270if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3))) {
271map->bios = BT_3;
272}
273else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2))) {
274map->bios = BT_2;
275}
276else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1))) {
277map->bios = BT_1;
278}
279else {
280printf("Unable to determine bios type.\n");
281printf("Please run the program 'dump_bios' as root and\n");
282printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");
283
284printf("Chipset: %s\n", chipset_type_names[map->chipset]);
285printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr));
286
287printf("Mode Table Entries: %u\n", map->mode_table_size);
288return 0;
289}
290
291return map;
292}
293
294void close_vbios(vbios_map * map) {
295FREE(map);
296}
297
298void unlock_vbios(vbios_map * map) {
299
300map->unlocked = TRUE;
301
302switch (map->chipset) {
303case CT_UNKWN:
304break;
305case CT_830:
306case CT_855GM:
307outl(0xcf8, 0x8000005a);
308map->b1 = inb(0xcfe);
309
310outl(0xcf8, 0x8000005a);
311outb(0xcfe, 0x33);
312break;
313case CT_845G:
314case CT_865G:
315case CT_915G:
316case CT_915GM:
317case CT_945G:
318case CT_945GM:
319case CT_945GME:
320case CT_946GZ:
321case CT_G965:
322case CT_Q965:
323case CT_965GM:
324case CT_500:
325
326outl(0xcf8, 0x80000090);
327map->b1 = inb(0xcfd);
328map->b2 = inb(0xcfe);
329outl(0xcf8, 0x80000090);
330outb(0xcfd, 0x33);
331outb(0xcfe, 0x33);
332break;
333}
334
335#if DEBUG
336{
337UInt32 t = inl(0xcfc);
338printf("unlock PAM: (0x%08x)\n", t);
339}
340#endif
341}
342
343void relock_vbios(vbios_map * map) {
344
345map->unlocked = FALSE;
346
347switch (map->chipset) {
348case CT_UNKWN:
349break;
350case CT_830:
351case CT_855GM:
352outl(0xcf8, 0x8000005a);
353outb(0xcfe, map->b1);
354break;
355case CT_845G:
356case CT_865G:
357case CT_915G:
358case CT_915GM:
359case CT_945G:
360case CT_945GM:
361case CT_945GME:
362case CT_946GZ:
363case CT_G965:
364case CT_Q965:
365case CT_965GM:
366case CT_500:
367
368outl(0xcf8, 0x80000090);
369outb(0xcfd, map->b1);
370outb(0xcfe, map->b2);
371break;
372}
373
374#if DEBUG
375{
376 UInt32 t = inl(0xcfc);
377printf("relock PAM: (0x%08x)\n", t);
378}
379#endif
380}
381
382
383static void gtf_timings(UInt32 x, UInt32 y, UInt32 freq,
384unsigned long *clock,
385UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank,
386UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank)
387{
388UInt32 hbl, vbl, vfreq;
389
390vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5;
391vfreq = vbl * freq;
392hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) /
393 + (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);
394
395*vsyncstart = y;
396*vsyncend = y + 3;
397*vblank = vbl - 1;
398*hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;
399*hsyncend = x + hbl / 2 - 1;
400*hblank = x + hbl - 1;
401*clock = (x + hbl) * vfreq / 1000;
402}
403
404void set_mode(vbios_map * map, /*UInt32 mode,*/ UInt32 x, UInt32 y, UInt32 bp, UInt32 htotal, UInt32 vtotal) {
405UInt32 xprev, yprev;
406UInt32 i = 0, j;// patch first available mode
407
408//for (i=0; i < map->mode_table_size; i++) {
409//if (map->mode_table[0].mode == mode) {
410switch(map->bios) {
411case BT_1:
412{
413vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
414
415if (bp) {
416map->mode_table[i].bits_per_pixel = bp;
417}
418
419res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0);
420res->x1 = (x & 0xff);
421
422res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0);
423res->y1 = (y & 0xff);
424if (htotal)
425res->x_total = ((htotal-x) & 0xff);
426
427if (vtotal)
428res->y_total = ((vtotal-y) & 0xff);
429}
430break;
431case BT_2:
432{
433vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
434
435res->xchars = x / 8;
436res->ychars = y / 16 - 1;
437xprev = res->modelines[0].x1;
438yprev = res->modelines[0].y1;
439
440for(j=0; j < 3; j++) {
441vbios_modeline_type2 * modeline = &res->modelines[j];
442
443if (modeline->x1 == xprev && modeline->y1 == yprev) {
444modeline->x1 = modeline->x2 = x-1;
445modeline->y1 = modeline->y2 = y-1;
446
447gtf_timings(x, y, freqs[j], &modeline->clock,
448&modeline->hsyncstart, &modeline->hsyncend,
449&modeline->hblank, &modeline->vsyncstart,
450&modeline->vsyncend, &modeline->vblank);
451
452if (htotal)
453modeline->htotal = htotal;
454else
455modeline->htotal = modeline->hblank;
456
457if (vtotal)
458modeline->vtotal = vtotal;
459else
460modeline->vtotal = modeline->vblank;
461}
462}
463}
464break;
465case BT_3:
466{
467vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
468
469xprev = res->modelines[0].x1;
470yprev = res->modelines[0].y1;
471
472for (j=0; j < 3; j++) {
473vbios_modeline_type3 * modeline = &res->modelines[j];
474
475if (modeline->x1 == xprev && modeline->y1 == yprev) {
476modeline->x1 = modeline->x2 = x-1;
477modeline->y1 = modeline->y2 = y-1;
478
479gtf_timings(x, y, freqs[j], &modeline->clock,
480&modeline->hsyncstart, &modeline->hsyncend,
481&modeline->hblank, &modeline->vsyncstart,
482&modeline->vsyncend, &modeline->vblank);
483if (htotal)
484modeline->htotal = htotal;
485else
486modeline->htotal = modeline->hblank;
487if (vtotal)
488modeline->vtotal = vtotal;
489else
490modeline->vtotal = modeline->vblank;
491
492modeline->timing_h = y-1;
493modeline->timing_v = x-1;
494}
495}
496}
497break;
498case BT_UNKWN:
499break;
500}
501//}
502//}
503}
504
505void display_map_info(vbios_map * map) {
506printf("Chipset: %s\n", chipset_type_names[map->chipset]);
507printf("BIOS: %s\n", bios_type_names[map->bios]);
508
509printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr));
510printf("Mode Table Entries: %u\n", map->mode_table_size);
511}
512
513/*
514int parse_args(int argc, char *argv[], chipset_type *forced_chipset, UInt32 *list, UInt32 *mode, UInt32 *x, UInt32 *y, UInt32 *bp, UInt32 *raw, UInt32 *htotal, UInt32 *vtotal) {
515UInt32 index = 0;
516
517*list = *mode = *x = *y = *raw = *htotal = *vtotal = 0;
518
519*forced_chipset = CT_UNKWN;
520
521if ((argc > index) && !strcmp(argv[index], "-c")) {
522index++;
523+
524+ if(argc<=index) {
525+ return 0;
526+ }
527+
528+ if (!strcmp(argv[index], "845")) {
529+ *forced_chipset = CT_845G;
530+ }
531+ else if (!strcmp(argv[index], "855")) {
532+ *forced_chipset = CT_855GM;
533+ }
534+ else if (!strcmp(argv[index], "865")) {
535+ *forced_chipset = CT_865G;
536+ }
537+ else if (!strcmp(argv[index], "915G")) {
538+ *forced_chipset = CT_915G;
539+ }
540+ else if (!strcmp(argv[index], "915GM")) {
541+ *forced_chipset = CT_915GM;
542+ }
543+ else if (!strcmp(argv[index], "945G")) {
544+ *forced_chipset = CT_945G;
545+ }
546+ else if (!strcmp(argv[index], "945GM")) {
547+ *forced_chipset = CT_945GM;
548+ }
549+ else if (!strcmp(argv[index], "945GME")) {
550+ *forced_chipset = CT_945GME;
551+ }
552+ else if (!strcmp(argv[index], "946GZ")) {
553+ *forced_chipset = CT_946GZ;
554+ }
555+ else if (!strcmp(argv[index], "G965")) {
556+ *forced_chipset = CT_G965;
557+ }
558+ else if (!strcmp(argv[index], "Q965")) {
559+ *forced_chipset = CT_Q965;
560+ }
561+ else if (!strcmp(argv[index], "500")) {
562+ *forced_chipset = CT_500;
563+ }
564
565+ else {
566+ printf("No match for forced chipset: %s\n", argv[index]);
567+ *forced_chipset = CT_UNKWN;
568+ }
569+
570+ index++;
571+
572+ if (argc<=index) {
573+ return 0;
574+ }
575+ }
576+
577+ if ((argc > index) && !strcmp(argv[index], "-l")) {
578+ *list = 1;
579+ index++;
580+
581+ if(argc<=index) {
582+ return 0;
583+ }
584+ }
585+
586+ if ((argc > index) && !strcmp(argv[index], "-r")) {
587+ *raw = 1;
588+ index++;
589+
590+ if(argc<=index) {
591+ return 0;
592+ }
593+ }
594+
595+ if (argc-index < 3 || argc-index > 6) {
596+ return -1;
597+ }
598+
599+ *mode = (UInt32) strtoul(argv[index], NULL, 16);
600+ *x = (UInt32)strtoul(argv[index+1], NULL, 10);
601+ *y = (UInt32)strtoul(argv[index+2], NULL, 10);
602+
603+
604+ if (argc-index > 3) {
605+ *bp = (UInt32)strtoul(argv[index+3], NULL, 10);
606+ }
607+ else {
608+ *bp = 0;
609+ }
610+
611+ if (argc-index > 4) {
612+ *htotal = (UInt32)strtoul(argv[index+4], NULL, 10);
613+ }
614+ else {
615+ *htotal = 0;
616+ }
617+
618+ if (argc-index > 5) {
619+ *vtotal = (UInt32)strtoul(argv[index+5], NULL, 10);
620+ }
621+ else {
622+ *vtotal = 0;
623+ }
624+
625+ return 0;
626+}
627+
628
629
630 */
631
632
633void list_modes(vbios_map *map, UInt32 raw) {
634 UInt32 i, x, y;
635
636 for (i=0; i < map->mode_table_size; i++) {
637 switch(map->bios) {
638case BT_1:
639 {
640 vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
641
642 x = ((((UInt32) res->x2) & 0xf0) << 4) | res->x1;
643 y = ((((UInt32) res->y2) & 0xf0) << 4) | res->y1;
644
645 if (x != 0 && y != 0) {
646 printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
647 }
648
649if (raw)
650{
651 printf("Mode %02x (raw) :\n\t%02x %02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n", map->mode_table[i].mode, res->unknow1[0],res->unknow1[1], res->x1,res->x_total,res->x2,res->y1,res->y_total,res->y2);
652}
653
654 }
655break;
656case BT_2:
657 {
658 vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
659
660 x = res->modelines[0].x1+1;
661 y = res->modelines[0].y1+1;
662
663 if (x != 0 && y != 0) {
664 printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
665 }
666 }
667break;
668case BT_3:
669 {
670 vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
671
672 x = res->modelines[0].x1+1;
673 y = res->modelines[0].y1+1;
674
675 if (x != 0 && y != 0) {
676 printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
677 }
678 }
679break;
680case BT_UNKWN:
681break;
682 }
683 }
684}
685
686
687void usage() {
688printf("Usage: 915resolution [-c chipset] [-l] [mode X Y] [bits/pixel] [htotal] [vtotal]\n");
689printf(" Set the resolution to XxY for a video mode\n");
690printf(" Bits per pixel are optional. htotal/vtotal settings are additionally optional.\n");
691printf(" Options:\n");
692printf(" -c force chipset type (THIS IS USED FOR DEBUG PURPOSES)\n");
693printf(" -l display the modes found in the video BIOS\n");
694printf(" -r display the modes found in the video BIOS in raw mode (THIS IS USED FOR DEBUG PURPOSES)\n");
695}
696
697/*
698static err_t
699cmd_915resolution (struct arg_list *state ,
700 int argc ,
701 char **argv )
702{
703vbios_map * map;
704UInt32 list, mode, x, y, bp, raw, htotal, vtotal;
705chipset_type forced_chipset;
706
707printf("Intel 500/800/900 Series VBIOS Hack : version %s\n\n", VERSION);
708
709if (parse_args(argc, argv, &forced_chipset, &list, &mode, &x, &y, &bp, &raw, &htotal, &vtotal) == -1) {
710usage();
711return 2;
712}
713
714map = open_vbios(forced_chipset);
715display_map_info(map);
716
717printf("\n");
718
719if (list) {
720list_modes(map, raw);
721}
722
723if (mode!=0 && x!=0 && y!=0) {
724unlock_vbios(map);
725
726set_mode(map, mode, x, y, bp, htotal, vtotal);
727
728relock_vbios(map);
729
730printf("Patch mode %02x to resolution %dx%d complete\n", mode, x, y);
731
732if (list) {
733list_modes(map, raw);
734}
735}
736
737close_vbios(map);
738
739return 0;
740}
741*/
742

Archive Download this file

Revision: 164