Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 141