Chameleon

Chameleon Svn Source Tree

Root/branches/valv/i386/libsaio/autoresolution.c

  • Property svn:executable set to
1/* Copied from 915 resolution created by steve tomljenovic
2 *
3 * This code is based on the techniques used in :
4 *
5 * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
6 * for demonstrating how to shadow the VBIOS into system RAM
7 * and then modify it.
8 *
9 * - 1280patch by Andrew Tipton (andrewtipton null li).
10 *
11 * - 855resolution by Alain Poirier
12 *
13 * This source code is into the public domain.
14 */
15
16#include "libsaio.h"
17//#include "autoresolution.h"
18#include "nvidia_resolution.h"
19#include "ati_resolution.h"
20#include "gma_resolution.h"
21#include "../boot2/graphics.h"
22
23char * chipsetTypeNames[] = {
24"UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME",
25"946GZ", "950GM", "955X", "G965", "Q965", "965GM", "975X",
26"P35", "X48", "B43", "Q45", "P45", "GM45", "G41", "G31", "G45", "500", "3150"
27};
28
29uint32_t getChipsetId(void)
30{
31outl(0xcf8, 0x80000000);
32return inl(0xcfc);
33}
34
35chipsetType getChipset(uint32_t id)
36{
37chipsetType type;
38
39switch (id)
40{
41case 0x35758086:
42type = CT_830;
43break;
44
45case 0x25608086:
46type = CT_845G;
47break;
48
49case 0x35808086:
50type = CT_855GM;
51break;
52
53case 0x25708086:
54type = CT_865G;
55break;
56
57case 0x25808086:
58type = CT_915G;
59break;
60
61case 0x25908086:
62type = CT_915GM;
63break;
64
65case 0x27708086:
66type = CT_945G;
67break;
68
69case 0x27748086:
70type = CT_955X;
71break;
72
73case 0x277c8086:
74type = CT_975X;
75break;
76
77case 0x27a08086:
78type = CT_945GM;
79break;
80
81case 0x27ac8086:
82type = CT_945GME;
83break;
84
85case 0x27ae8086:
86type = CT_950GM;
87break;
88
89case 0x29708086:
90type = CT_946GZ;
91break;
92
93case 0x29a08086:
94type = CT_G965;
95break;
96
97case 0x29908086:
98type = CT_Q965;
99break;
100
101case 0x2a008086:
102type = CT_965GM;
103break;
104
105case 0x29e08086:
106type = CT_X48;
107break;
108
109case 0x2a408086:
110type = CT_GM45;
111break;
112
113case 0x2e108086:
114case 0X2e908086:
115type = CT_B43;
116break;
117
118case 0x2e208086:
119type = CT_P45;
120break;
121
122case 0x2e308086:
123type = CT_G41;
124break;
125
126case 0x29c08086:
127type = CT_G31;
128break;
129
130case 0x29208086:
131type = CT_G45;
132break;
133
134case 0x81008086:
135type = CT_500;
136break;
137
138case 0xA0108086:
139type = CT_3150;
140break;
141
142default:
143type = CT_UNKWN;
144break;
145}
146return type;
147}
148
149
150void gtfTimings(uint32_t x, uint32_t y, uint32_t freq,
151 uint32_t *clock,
152 uint16_t *hSyncStart, uint16_t *hSyncEnd, uint16_t *hBlank,
153 uint16_t *vSyncStart, uint16_t *vSyncEnd, uint16_t *vBlank)
154{
155uint32_t hbl, vbl, vfreq;
156
157vbl = y + (y+1)/(20000/(11*freq) - 1) + 1;
158
159vfreq = vbl * freq;
160hbl = 16 * (int)(x * (30 - 300000 / vfreq) /
161 + (70 + 300000 / vfreq) / 16 + 0);
162
163*vSyncStart = y;
164*vSyncEnd = y + 3;
165*vBlank = vbl;
166*hSyncStart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 ;
167*hSyncEnd = x + hbl / 2;
168*hBlank = x + hbl;
169*clock = (x + hbl) * vfreq / 1000;
170}
171
172
173void getAspectRatio(sAspect* aspect, uint32_t x, uint32_t y)
174{
175if ((y * 16 / 9) == x)
176{
177aspect->width = 16;
178aspect->height = 9;
179}
180else if ((y * 16 / 10) == x)
181{
182aspect->width = 16;
183aspect->height = 10;
184}
185else if ((y * 5 / 4) == x)
186{
187aspect->width = 5;
188aspect->height = 4;
189}
190else if ((y * 15 / 9) == x)
191{
192aspect->width = 15;
193aspect->height = 9;
194}
195else
196{
197aspect->width = 4;
198aspect->height = 3;
199}
200PRINT("Aspect Ratio is %d/%d\n", aspect->width, aspect->height);
201}
202
203
204/*
205 * initialize the mode tables chain
206 * tablesCount represents the number of VESA tables in the vBios
207 * return value is a pointer to the first table
208 */
209sModeTable * intializeTables(vBiosMap * map, int tablesCount) {
210map->modeTables = (sModeTable *)malloc(sizeof(sModeTable));
211sModeTable * table = map->modeTables;
212
213PRINT("Creating %d Mode Tables\n", tablesCount);
214
215int i = tablesCount;
216while ( i != 0 )
217{
218table->id = tablesCount - i;
219PRINT("New table with id: %d\n", table->id);
220
221// opening the chain if it's the first table
222if (i == tablesCount)
223table->prev = NULL;
224else // attache the table to the chain
225table->prev = table;
226
227//if there is more than one table, alloc the next one
228if (i > 1)
229{
230table->next = (sModeTable *)malloc(sizeof(sModeTable));
231table = table->next;
232}
233else // no more table, close the chain
234table->next = NULL;
235
236i--;
237}
238
239return map->modeTables;
240}
241
242
243//void closeVbios(vBiosMap * map); azi: dup - declared on header
244
245vBiosMap * openVbios(chipsetType forcedChipset)
246{
247uint32_t z;
248vBiosMap * map = NEW(vBiosMap);
249
250for(z = 0; z < sizeof(vBiosMap); z++)
251((char*)map)[z] = 0;
252
253/*
254 * Determine chipset
255 */
256
257if (forcedChipset == CT_UNKWN)
258{
259map->chipsetId = getChipsetId();
260map->chipset = getChipset(map->chipsetId);
261PRINT("Chipset is %s (pci id 0x%x)\n",chipsetTypeNames[map->chipset], map->chipsetId);
262}
263else if (forcedChipset != CT_UNKWN)
264{
265map->chipset = forcedChipset;
266}
267else
268{
269map->chipset = CT_915GM;
270}
271
272/*
273 * Map the video bios to memory
274 */
275
276map->biosPtr=(uint8_t*)VBIOS_START;
277
278/*
279 * Common initialisation
280 */
281
282map->hasSwitched = false;
283
284/*
285 * check if we have ATI Radeon and open atombios
286 */
287atiBiosTables atiTables;
288
289atiTables.base = map->biosPtr;
290atiTables.atomRomHeader = (atomRomHeader *) (map->biosPtr + *(uint16_t *) (map->biosPtr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER));
291
292if (strcmp ((char *) atiTables.atomRomHeader->firmWareSignature, "ATOM") == 0)
293{
294map->bios = BT_ATI_1;
295PRINT("We have an AtomBios Card\n");
296return openAtiVbios(map, atiTables);
297}
298
299
300/*
301 * check if we have NVidia
302 */
303if (map->bios != BT_ATI_1)
304{
305int i = 0;
306while (i < 512) // we don't need to look through the whole bios, just the first 512 bytes
307{
308if ((map->biosPtr[i] == 'N')
309&& (map->biosPtr[i+1] == 'V')
310&& (map->biosPtr[i+2] == 'I')
311&& (map->biosPtr[i+3] == 'D'))
312{
313map->bios = BT_NVDA;
314PRINT("We have an NVIDIA Card\n");
315return openNvidiaVbios(map);
316break;
317}
318i++;
319}
320}
321
322/*
323 * check if we have Intel
324 */
325
326if ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA))
327{
328int i = 0;
329while (i < VBIOS_SIZE)
330{
331if ((map->biosPtr[i] == 'I')
332&& (map->biosPtr[i+1] == 'n')
333&& (map->biosPtr[i+2] == 't')
334&& (map->biosPtr[i+3] == 'e')
335&& (map->biosPtr[i+4] == 'l'))
336{
337map->bios = BT_1;
338PRINT("We have an Intel Card\n");
339saveVbios(map);
340return openIntelVbios(map);
341break;
342}
343i++;
344}
345}
346
347/*
348 * Unidentified Chipset
349 */
350
351if ( (map->chipset == CT_UNKWN) || ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA) && (map->bios != BT_1)) )
352{
353PRINT("Unknown chipset type and unrecognized bios.\n");
354
355PRINT("autoresolution only works with Intel 800/900 series graphic chipsets.\n");
356
357PRINT("Chipset Id: %x\n", map->chipsetId);
358closeVbios(map);
359return 0;
360}
361
362/*
363 * Should never get there
364 */
365return 0;
366}
367
368void closeVbios(vBiosMap * map)
369{
370PRINT("Closing VBios\n");
371//make sure to turn autoResolution off
372if (gAutoResolution == true)
373gAutoResolution = false;
374
375// if we saved the vBios, free the copy
376if (map->biosBackupPtr != NULL)
377{
378PRINT("Freeing biosBackupPtr\t");
379FREE(map->biosBackupPtr);
380PRINT("[OK]\n");
381}
382
383// free table backups if any
384sModeTable * table = map->modeTables;
385while (table != NULL)
386{
387if (table->backup != NULL)
388{
389PRINT("Table #%d: Freeing backup\t", table->id);
390FREE(table->backup);
391PRINT("[OK]\n");
392}
393
394if (table != NULL)
395{
396PRINT("Table #%d: Freeing\t\t", table->id);
397FREE(table);
398PRINT("[OK]\n");
399}
400
401if (table->next == NULL)
402break;
403
404table = table->next;
405}
406
407PRINT("Freeing map\t\t\t");
408FREE(map);
409PRINT("[OK]\n");
410}
411
412void unlockVbios(vBiosMap * map)
413{
414
415map->unlocked = true;
416
417switch (map->chipset)
418{
419case CT_UNKWN:
420break;
421case CT_830:
422case CT_855GM:
423outl(0xcf8, 0x8000005a);
424map->b1 = inb(0xcfe);
425
426outl(0xcf8, 0x8000005a);
427outb(0xcfe, 0x33);
428break;
429case CT_845G:
430case CT_865G:
431case CT_915G:
432case CT_915GM:
433case CT_945G:
434case CT_945GM:
435case CT_945GME:
436case CT_946GZ:
437case CT_950GM:
438case CT_955X:
439case CT_G965:
440case CT_Q965:
441case CT_965GM:
442case CT_975X:
443case CT_P35:
444case CT_X48:
445case CT_B43:
446case CT_Q45:
447case CT_P45:
448case CT_GM45:
449case CT_G41:
450case CT_G31:
451case CT_G45:
452case CT_500:
453case CT_3150:
454
455outl(0xcf8, 0x80000090);
456map->b1 = inb(0xcfd);
457map->b2 = inb(0xcfe);
458outl(0xcf8, 0x80000090);
459outb(0xcfd, 0x33);
460outb(0xcfe, 0x33);
461break;
462}
463
464#if DEBUG
465{
466uint32_t t = inl(0xcfc);
467PRINT("unlock PAM: (0x%08x)\n", t);
468}
469#endif
470}
471
472void relockVbios(vBiosMap * map)
473{
474
475map->unlocked = false;
476
477switch (map->chipset)
478{
479case CT_UNKWN:
480break;
481case CT_830:
482case CT_855GM:
483outl(0xcf8, 0x8000005a);
484outb(0xcfe, map->b1);
485break;
486case CT_845G:
487case CT_865G:
488case CT_915G:
489case CT_915GM:
490case CT_945G:
491case CT_945GM:
492case CT_945GME:
493case CT_946GZ:
494case CT_950GM:
495case CT_955X:
496case CT_G965:
497case CT_Q965:
498case CT_965GM:
499case CT_975X:
500case CT_P35:
501case CT_X48:
502case CT_B43:
503case CT_Q45:
504case CT_P45:
505case CT_GM45:
506case CT_G41:
507case CT_G31:
508case CT_G45:
509case CT_500:
510case CT_3150:
511outl(0xcf8, 0x80000090);
512outb(0xcfd, map->b1);
513outb(0xcfe, map->b2);
514break;
515}
516
517#if DEBUG
518{
519 uint32_t t = inl(0xcfc);
520PRINT("relock PAM: (0x%08x)\n", t);
521}
522#endif
523}
524
525/*
526 * saveVbios - save the entire vBios in case the patch has to be removed
527 */
528void saveVbios(vBiosMap * map)
529{
530map->biosBackupPtr = malloc(VBIOS_SIZE);
531bcopy((const uint8_t *)0xC0000, map->biosBackupPtr, VBIOS_SIZE);
532}
533
534/*
535 * restoreVbios - restore the vBios backup or table backups if any
536 */
537void restoreVbios(vBiosMap * map)
538{
539if ((map->bios == BT_ATI_1) || (map->bios == BT_ATI_2) || (map->bios == BT_NVDA))
540{
541restoreTables(map, map->modeTables);
542}
543else
544{
545unlockVbios(map);
546bcopy(map->biosBackupPtr,(uint8_t *)0xC0000, VBIOS_SIZE);
547relockVbios(map);
548}
549}
550
551/*
552 * saveTables - save the tables in case the patch has to be removed
553 */
554void saveTables(sModeTable * table)
555{
556while (table != NULL)
557{
558table->backup = (uint8_t *)malloc(table->size);
559bcopy((const uint8_t *)table->pointer, table->backup, table->size);
560table = table->next;
561}
562}
563
564/*
565 * restoreTables - restore tables backup
566 */
567void restoreTables(vBiosMap * map, sModeTable * table)
568{
569unlockVbios(map);
570while (table != NULL)
571{
572bcopy(table->backup, (uint8_t *)table->pointer, table->size);
573table = table->next;
574}
575relockVbios(map);
576}
577
578/*
579 * patchVbios - call the vendor specific function to patch the VESA tables
580 * x & y are horizontal and vertical dimensions respectively, in pixels
581 * for GMA and ATI, only first mode in Table is patched
582 *
583 * each vendor specific function have the same form :
584 * bool vendorSetMode_type(sModeTable * table, uint8_t index, uint32_t * x, uint32_t * y);
585 * where 'table' is the VESA table to patch, 'index' is the index of the mode in table,
586 * 'x' & 'y' are pointer to the target resolution and return the next resolution in table.
587 */
588void patchVbios(vBiosMap * map, uint32_t x, uint32_t y, uint32_t bp, uint32_t hTotal, uint32_t vTotal)
589{
590uint32_t i = 0;
591
592sModeTable * table = map->modeTables;
593
594// save the target resolution for future use
595map->currentX = x;
596map->currentY = y;
597
598unlockVbios(map);
599
600// Get the aspect ratio for the requested mode
601getAspectRatio(&map->aspectRatio, x, y);
602
603i = 0;
604
605// Call the vendor specific function for each available VESA Table
606table = map->modeTables;
607while (table != NULL)
608{
609//reset resolution value before treating a new table
610x = map->currentX;
611y = map->currentY;
612
613PRINT("Patching Table #%d: \n", table->id);
614
615map->setMode(table, i, &x, &y);
616#ifdef AUTORES_DEBUG
617pause();
618#endif
619
620table = table->next;
621}
622
623relockVbios(map);
624return;
625}
626

Archive Download this file

Revision: 709