Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 495