Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 399