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) {
213/*
214printf("Unknown chipset type and unrecognized bios.\n");
215
216printf("915resolution only works with Intel 800/900 series graphic chipsets.\n");
217*/
218printf("Chipset Id: %x\n", map->chipset_id);
219close_vbios(map);
220return 0;
221}
222
223/*
224 * Figure out where the mode table is
225 */
226
227{
228char* p = map->bios_ptr + 16;
229char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));
230
231while (p < limit && map->mode_table == 0) {
232vbios_mode * mode_ptr = (vbios_mode *) p;
233
234if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&
235((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {
236
237map->mode_table = mode_ptr;
238}
239
240p++;
241}
242
243if (map->mode_table == 0) {
244printf("Unable to locate the mode table.\n");
245printf("Please run the program 'dump_bios' as root and\n");
246printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");
247printf("Chipset: %s\n", chipset_type_names[map->chipset]);
248close_vbios(map);
249return 0;
250}
251}
252
253/*
254 * Determine size of mode table
255 */
256
257{
258vbios_mode * mode_ptr = map->mode_table;
259
260while (mode_ptr->mode != 0xff) {
261map->mode_table_size++;
262mode_ptr++;
263}
264}
265
266/*
267 * Figure out what type of bios we have
268 * order of detection is important
269 */
270
271if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3))) {
272map->bios = BT_3;
273}
274else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2))) {
275map->bios = BT_2;
276}
277else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1))) {
278map->bios = BT_1;
279}
280else {
281printf("Unable to determine bios type.\n");
282printf("Please run the program 'dump_bios' as root and\n");
283printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");
284
285printf("Chipset: %s\n", chipset_type_names[map->chipset]);
286printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr));
287
288printf("Mode Table Entries: %u\n", map->mode_table_size);
289return 0;
290}
291
292return map;
293}
294
295void close_vbios(vbios_map * map) {
296FREE(map);
297}
298
299void unlock_vbios(vbios_map * map) {
300
301map->unlocked = TRUE;
302
303switch (map->chipset) {
304case CT_UNKWN:
305break;
306case CT_830:
307case CT_855GM:
308outl(0xcf8, 0x8000005a);
309map->b1 = inb(0xcfe);
310
311outl(0xcf8, 0x8000005a);
312outb(0xcfe, 0x33);
313break;
314case CT_845G:
315case CT_865G:
316case CT_915G:
317case CT_915GM:
318case CT_945G:
319case CT_945GM:
320case CT_945GME:
321case CT_946GZ:
322case CT_G965:
323case CT_Q965:
324case CT_965GM:
325case CT_500:
326
327outl(0xcf8, 0x80000090);
328map->b1 = inb(0xcfd);
329map->b2 = inb(0xcfe);
330outl(0xcf8, 0x80000090);
331outb(0xcfd, 0x33);
332outb(0xcfe, 0x33);
333break;
334}
335
336#if DEBUG
337{
338UInt32 t = inl(0xcfc);
339printf("unlock PAM: (0x%08x)\n", t);
340}
341#endif
342}
343
344void relock_vbios(vbios_map * map) {
345
346map->unlocked = FALSE;
347
348switch (map->chipset) {
349case CT_UNKWN:
350break;
351case CT_830:
352case CT_855GM:
353outl(0xcf8, 0x8000005a);
354outb(0xcfe, map->b1);
355break;
356case CT_845G:
357case CT_865G:
358case CT_915G:
359case CT_915GM:
360case CT_945G:
361case CT_945GM:
362case CT_945GME:
363case CT_946GZ:
364case CT_G965:
365case CT_Q965:
366case CT_965GM:
367case CT_500:
368
369outl(0xcf8, 0x80000090);
370outb(0xcfd, map->b1);
371outb(0xcfe, map->b2);
372break;
373}
374
375#if DEBUG
376{
377 UInt32 t = inl(0xcfc);
378printf("relock PAM: (0x%08x)\n", t);
379}
380#endif
381}
382
383
384static void gtf_timings(UInt32 x, UInt32 y, UInt32 freq,
385unsigned long *clock,
386UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank,
387UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank)
388{
389UInt32 hbl, vbl, vfreq;
390
391vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5;
392vfreq = vbl * freq;
393hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) /
394 + (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);
395
396*vsyncstart = y;
397*vsyncend = y + 3;
398*vblank = vbl - 1;
399*hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;
400*hsyncend = x + hbl / 2 - 1;
401*hblank = x + hbl - 1;
402*clock = (x + hbl) * vfreq / 1000;
403}
404
405void set_mode(vbios_map * map, /*UInt32 mode,*/ UInt32 x, UInt32 y, UInt32 bp, UInt32 htotal, UInt32 vtotal) {
406UInt32 xprev, yprev;
407UInt32 i = 0, j;// patch first available mode
408
409//for (i=0; i < map->mode_table_size; i++) {
410//if (map->mode_table[0].mode == mode) {
411switch(map->bios) {
412case BT_1:
413{
414vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
415
416if (bp) {
417map->mode_table[i].bits_per_pixel = bp;
418}
419
420res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0);
421res->x1 = (x & 0xff);
422
423res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0);
424res->y1 = (y & 0xff);
425if (htotal)
426res->x_total = ((htotal-x) & 0xff);
427
428if (vtotal)
429res->y_total = ((vtotal-y) & 0xff);
430}
431break;
432case BT_2:
433{
434vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
435
436res->xchars = x / 8;
437res->ychars = y / 16 - 1;
438xprev = res->modelines[0].x1;
439yprev = res->modelines[0].y1;
440
441for(j=0; j < 3; j++) {
442vbios_modeline_type2 * modeline = &res->modelines[j];
443
444if (modeline->x1 == xprev && modeline->y1 == yprev) {
445modeline->x1 = modeline->x2 = x-1;
446modeline->y1 = modeline->y2 = y-1;
447
448gtf_timings(x, y, freqs[j], &modeline->clock,
449&modeline->hsyncstart, &modeline->hsyncend,
450&modeline->hblank, &modeline->vsyncstart,
451&modeline->vsyncend, &modeline->vblank);
452
453if (htotal)
454modeline->htotal = htotal;
455else
456modeline->htotal = modeline->hblank;
457
458if (vtotal)
459modeline->vtotal = vtotal;
460else
461modeline->vtotal = modeline->vblank;
462}
463}
464}
465break;
466case BT_3:
467{
468vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
469
470xprev = res->modelines[0].x1;
471yprev = res->modelines[0].y1;
472
473for (j=0; j < 3; j++) {
474vbios_modeline_type3 * modeline = &res->modelines[j];
475
476if (modeline->x1 == xprev && modeline->y1 == yprev) {
477modeline->x1 = modeline->x2 = x-1;
478modeline->y1 = modeline->y2 = y-1;
479
480gtf_timings(x, y, freqs[j], &modeline->clock,
481&modeline->hsyncstart, &modeline->hsyncend,
482&modeline->hblank, &modeline->vsyncstart,
483&modeline->vsyncend, &modeline->vblank);
484if (htotal)
485modeline->htotal = htotal;
486else
487modeline->htotal = modeline->hblank;
488if (vtotal)
489modeline->vtotal = vtotal;
490else
491modeline->vtotal = modeline->vblank;
492
493modeline->timing_h = y-1;
494modeline->timing_v = x-1;
495}
496}
497}
498break;
499case BT_UNKWN:
500break;
501}
502//}
503//}
504}
505
506void display_map_info(vbios_map * map) {
507printf("Chipset: %s\n", chipset_type_names[map->chipset]);
508printf("BIOS: %s\n", bios_type_names[map->bios]);
509
510printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr));
511printf("Mode Table Entries: %u\n", map->mode_table_size);
512}
513
514/*
515int 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) {
516UInt32 index = 0;
517
518*list = *mode = *x = *y = *raw = *htotal = *vtotal = 0;
519
520*forced_chipset = CT_UNKWN;
521
522if ((argc > index) && !strcmp(argv[index], "-c")) {
523index++;
524+
525+ if(argc<=index) {
526+ return 0;
527+ }
528+
529+ if (!strcmp(argv[index], "845")) {
530+ *forced_chipset = CT_845G;
531+ }
532+ else if (!strcmp(argv[index], "855")) {
533+ *forced_chipset = CT_855GM;
534+ }
535+ else if (!strcmp(argv[index], "865")) {
536+ *forced_chipset = CT_865G;
537+ }
538+ else if (!strcmp(argv[index], "915G")) {
539+ *forced_chipset = CT_915G;
540+ }
541+ else if (!strcmp(argv[index], "915GM")) {
542+ *forced_chipset = CT_915GM;
543+ }
544+ else if (!strcmp(argv[index], "945G")) {
545+ *forced_chipset = CT_945G;
546+ }
547+ else if (!strcmp(argv[index], "945GM")) {
548+ *forced_chipset = CT_945GM;
549+ }
550+ else if (!strcmp(argv[index], "945GME")) {
551+ *forced_chipset = CT_945GME;
552+ }
553+ else if (!strcmp(argv[index], "946GZ")) {
554+ *forced_chipset = CT_946GZ;
555+ }
556+ else if (!strcmp(argv[index], "G965")) {
557+ *forced_chipset = CT_G965;
558+ }
559+ else if (!strcmp(argv[index], "Q965")) {
560+ *forced_chipset = CT_Q965;
561+ }
562+ else if (!strcmp(argv[index], "500")) {
563+ *forced_chipset = CT_500;
564+ }
565
566+ else {
567+ printf("No match for forced chipset: %s\n", argv[index]);
568+ *forced_chipset = CT_UNKWN;
569+ }
570+
571+ index++;
572+
573+ if (argc<=index) {
574+ return 0;
575+ }
576+ }
577+
578+ if ((argc > index) && !strcmp(argv[index], "-l")) {
579+ *list = 1;
580+ index++;
581+
582+ if(argc<=index) {
583+ return 0;
584+ }
585+ }
586+
587+ if ((argc > index) && !strcmp(argv[index], "-r")) {
588+ *raw = 1;
589+ index++;
590+
591+ if(argc<=index) {
592+ return 0;
593+ }
594+ }
595+
596+ if (argc-index < 3 || argc-index > 6) {
597+ return -1;
598+ }
599+
600+ *mode = (UInt32) strtoul(argv[index], NULL, 16);
601+ *x = (UInt32)strtoul(argv[index+1], NULL, 10);
602+ *y = (UInt32)strtoul(argv[index+2], NULL, 10);
603+
604+
605+ if (argc-index > 3) {
606+ *bp = (UInt32)strtoul(argv[index+3], NULL, 10);
607+ }
608+ else {
609+ *bp = 0;
610+ }
611+
612+ if (argc-index > 4) {
613+ *htotal = (UInt32)strtoul(argv[index+4], NULL, 10);
614+ }
615+ else {
616+ *htotal = 0;
617+ }
618+
619+ if (argc-index > 5) {
620+ *vtotal = (UInt32)strtoul(argv[index+5], NULL, 10);
621+ }
622+ else {
623+ *vtotal = 0;
624+ }
625+
626+ return 0;
627+}
628+
629
630
631 */
632
633
634void list_modes(vbios_map *map, UInt32 raw) {
635 UInt32 i, x, y;
636
637 for (i=0; i < map->mode_table_size; i++) {
638 switch(map->bios) {
639case BT_1:
640 {
641 vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
642
643 x = ((((UInt32) res->x2) & 0xf0) << 4) | res->x1;
644 y = ((((UInt32) res->y2) & 0xf0) << 4) | res->y1;
645
646 if (x != 0 && y != 0) {
647 printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
648 }
649
650if (raw)
651{
652 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);
653}
654
655 }
656break;
657case BT_2:
658 {
659 vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
660
661 x = res->modelines[0].x1+1;
662 y = res->modelines[0].y1+1;
663
664 if (x != 0 && y != 0) {
665 printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
666 }
667 }
668break;
669case BT_3:
670 {
671 vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
672
673 x = res->modelines[0].x1+1;
674 y = res->modelines[0].y1+1;
675
676 if (x != 0 && y != 0) {
677 printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
678 }
679 }
680break;
681case BT_UNKWN:
682break;
683 }
684 }
685}
686
687
688void usage() {
689printf("Usage: 915resolution [-c chipset] [-l] [mode X Y] [bits/pixel] [htotal] [vtotal]\n");
690printf(" Set the resolution to XxY for a video mode\n");
691printf(" Bits per pixel are optional. htotal/vtotal settings are additionally optional.\n");
692printf(" Options:\n");
693printf(" -c force chipset type (THIS IS USED FOR DEBUG PURPOSES)\n");
694printf(" -l display the modes found in the video BIOS\n");
695printf(" -r display the modes found in the video BIOS in raw mode (THIS IS USED FOR DEBUG PURPOSES)\n");
696}
697
698/*
699static err_t
700cmd_915resolution (struct arg_list *state ,
701 int argc ,
702 char **argv )
703{
704vbios_map * map;
705UInt32 list, mode, x, y, bp, raw, htotal, vtotal;
706chipset_type forced_chipset;
707
708printf("Intel 500/800/900 Series VBIOS Hack : version %s\n\n", VERSION);
709
710if (parse_args(argc, argv, &forced_chipset, &list, &mode, &x, &y, &bp, &raw, &htotal, &vtotal) == -1) {
711usage();
712return 2;
713}
714
715map = open_vbios(forced_chipset);
716display_map_info(map);
717
718printf("\n");
719
720if (list) {
721list_modes(map, raw);
722}
723
724if (mode!=0 && x!=0 && y!=0) {
725unlock_vbios(map);
726
727set_mode(map, mode, x, y, bp, htotal, vtotal);
728
729relock_vbios(map);
730
731printf("Patch mode %02x to resolution %dx%d complete\n", mode, x, y);
732
733if (list) {
734list_modes(map, raw);
735}
736}
737
738close_vbios(map);
739
740return 0;
741}
742*/
743

Archive Download this file

Revision: 172