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

Archive Download this file

Revision: 69