Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 515