Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/trunkAutoResolution/i386/libsaio/autoresolution.c

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

Archive Download this file

Revision: 946