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 "boot.h"
19//#include "gui.h"
20#include "nvidia_resolution.h"
21#include "ati_resolution.h"
22#include "gma_resolution.h"
23#include "../boot2/graphics.h" //Azi:reminder
24
25char * chipsetTypeNames[] = {
26"UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME",
27"946GZ", "955X", "G965", "Q965", "965GM", "975X",
28"P35", "X48", "B43", "Q45", "P45", "GM45", "G41", "G31", "G45", "500"
29};
30
31uint32_t getChipsetId(void)
32{
33outl(0xcf8, 0x80000000);
34return inl(0xcfc);
35}
36
37chipsetType getChipset(uint32_t id)
38{
39chipsetType type;
40
41switch (id)
42{
43case 0x35758086:
44type = CT_830;
45break;
46
47case 0x25608086:
48type = CT_845G;
49break;
50
51case 0x35808086:
52type = CT_855GM;
53break;
54
55case 0x25708086:
56type = CT_865G;
57break;
58
59case 0x25808086:
60type = CT_915G;
61break;
62
63case 0x25908086:
64type = CT_915GM;
65break;
66
67case 0x27708086:
68type = CT_945G;
69break;
70
71case 0x27748086:
72type = CT_955X;
73break;
74
75case 0x277c8086:
76type = CT_975X;
77break;
78
79case 0x27a08086:
80type = CT_945GM;
81break;
82
83case 0x27ac8086:
84type = CT_945GME;
85break;
86
87case 0x29708086:
88type = CT_946GZ;
89break;
90
91case 0x29a08086:
92type = CT_G965;
93break;
94
95case 0x29908086:
96type = CT_Q965;
97break;
98
99case 0x2a008086:
100type = CT_965GM;
101break;
102
103case 0x29e08086:
104type = CT_X48;
105break;
106
107case 0x2a408086:
108type = CT_GM45;
109break;
110
111case 0x2e108086:
112case 0X2e908086:
113type = CT_B43;
114break;
115
116case 0x2e208086:
117type = CT_P45;
118break;
119
120case 0x2e308086:
121type = CT_G41;
122break;
123
124case 0x29c08086:
125type = CT_G31;
126break;
127
128case 0x29208086:
129type = CT_G45;
130break;
131
132case 0x81008086:
133type = CT_500;
134break;
135
136default:
137type = CT_UNKWN;
138break;
139}
140return type;
141}
142
143
144void gtfTimings(uint32_t x, uint32_t y, uint32_t freq,
145 uint32_t *clock,
146 uint16_t *hSyncStart, uint16_t *hSyncEnd, uint16_t *hBlank,
147 uint16_t *vSyncStart, uint16_t *vSyncEnd, uint16_t *vBlank)
148{
149uint32_t hbl, vbl, vfreq;
150
151vbl = y + (y+1)/(20000/(11*freq) - 1) + 1;
152
153vfreq = vbl * freq;
154hbl = 16 * (int)(x * (30 - 300000 / vfreq) /
155 + (70 + 300000 / vfreq) / 16 + 0);
156
157*vSyncStart = y;
158*vSyncEnd = y + 3;
159*vBlank = vbl;
160*hSyncStart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 ;
161*hSyncEnd = x + hbl / 2;
162*hBlank = x + hbl;
163*clock = (x + hbl) * vfreq / 1000;
164}
165
166
167void getAspectRatio(sAspect* aspect, uint32_t x, uint32_t y)
168{
169if ((y * 16 / 9) == x)
170{
171aspect->width = 16;
172aspect->height = 9;
173}
174else if ((y * 16 / 10) == x)
175{
176aspect->width = 16;
177aspect->height = 10;
178}
179else if ((y * 5 / 4) == x)
180{
181aspect->width = 5;
182aspect->height = 4;
183}
184else if ((y * 15 / 9) == x)
185{
186aspect->width = 15;
187aspect->height = 9;
188}
189else
190{
191aspect->width = 4;
192aspect->height = 3;
193}
194PRINT("Aspect Ratio is %d/%d\n", aspect->width, aspect->height);
195}
196
197
198/*
199 * initialize the mode tables chain
200 * tablesCount represents the number of VESA tables in the vBios
201 * return value is a pointer to the first table
202 */
203sModeTable * intializeTables(vBiosMap * map, int tablesCount) {
204map->modeTables = (sModeTable *)malloc(sizeof(sModeTable));
205sModeTable * table = map->modeTables;
206
207PRINT("Creating %d Mode Tables\n", tablesCount);
208
209int i = tablesCount;
210while ( i != 0 )
211{
212table->id = tablesCount - i;
213PRINT("New table with id: %d\n", table->id);
214
215// opening the chain if it's the first table
216if (i == tablesCount)
217table->prev = NULL;
218else // attache the table to the chain
219table->prev = table;
220
221//if there is more than one table, alloc the next one
222if (i > 1)
223{
224table->next = (sModeTable *)malloc(sizeof(sModeTable));
225table = table->next;
226}
227else // no more table, close the chain
228table->next = NULL;
229
230i--;
231}
232
233return map->modeTables;
234}
235
236
237//void closeVbios(vBiosMap * map); azi: dup - declared on header
238
239vBiosMap * openVbios(chipsetType forcedChipset)
240{
241uint32_t z;
242vBiosMap * map = NEW(vBiosMap);
243
244for(z = 0; z < sizeof(vBiosMap); z++)
245((char*)map)[z] = 0;
246
247/*
248 * Determine chipset
249 */
250
251if (forcedChipset == CT_UNKWN)
252{
253map->chipsetId = getChipsetId();
254map->chipset = getChipset(map->chipsetId);
255PRINT("Chipset is %s (pci id 0x%x)\n",chipsetTypeNames[map->chipset], map->chipsetId);
256}
257else if (forcedChipset != CT_UNKWN)
258{
259map->chipset = forcedChipset;
260}
261else
262{
263map->chipset = CT_915GM;
264}
265
266/*
267 * Map the video bios to memory
268 */
269
270map->biosPtr=(uint8_t*)VBIOS_START;
271
272/*
273 * Common initialisation
274 */
275
276//map->hasSwitched = false;
277
278/*
279 * check if we have ATI Radeon and open atombios
280 */
281atiBiosTables atiTables;
282
283atiTables.base = map->biosPtr;
284atiTables.atomRomHeader = (atomRomHeader *) (map->biosPtr + *(uint16_t *) (map->biosPtr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER));
285
286if (strcmp ((char *) atiTables.atomRomHeader->firmWareSignature, "ATOM") == 0)
287{
288map->bios = BT_ATI_1;
289PRINT("We have an AtomBios Card\n");
290return openAtiVbios(map, atiTables);
291}
292
293
294/*
295 * check if we have NVidia
296 */
297if (map->bios != BT_ATI_1)
298{
299int i = 0;
300while (i < 512) // we don't need to look through the whole bios, just the first 512 bytes
301{
302if ((map->biosPtr[i] == 'N')
303&& (map->biosPtr[i+1] == 'V')
304&& (map->biosPtr[i+2] == 'I')
305&& (map->biosPtr[i+3] == 'D'))
306{
307map->bios = BT_NVDA;
308PRINT("We have an NVIDIA Card\n");
309return openNvidiaVbios(map);
310break;
311}
312i++;
313}
314}
315
316/*
317 * check if we have Intel
318 */
319
320if ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA))
321{
322int i = 0;
323while (i < VBIOS_SIZE)
324{
325if ((map->biosPtr[i] == 'I')
326&& (map->biosPtr[i+1] == 'n')
327&& (map->biosPtr[i+2] == 't')
328&& (map->biosPtr[i+3] == 'e')
329&& (map->biosPtr[i+4] == 'l'))
330{
331map->bios = BT_1;
332PRINT("We have an Intel Card\n");
333saveVbios(map);
334return openIntelVbios(map);
335break;
336}
337i++;
338}
339}
340
341/*
342 * Unidentified Chipset
343 */
344
345if ( (map->chipset == CT_UNKWN) || ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA) && (map->bios != BT_1)) )
346{
347PRINT("Unknown chipset type and unrecognized bios.\n");
348
349PRINT("autoresolution only works with Intel 800/900 series graphic chipsets.\n"); //Azi:reminder
350
351PRINT("Chipset Id: %x\n", map->chipsetId);
352closeVbios(map);
353return 0;
354}
355
356/*
357 * Should never get there
358 */
359return 0;
360}
361
362void closeVbios(vBiosMap * map)
363{
364PRINT("Closing VBios\n");
365//make sure to turn autoResolution off
366if (gAutoResolution == true)
367gAutoResolution = false;
368
369// if we saved the vBios, free the copy
370if (map->biosBackupPtr != NULL)
371{
372PRINT("Freeing biosBackupPtr\t");
373FREE(map->biosBackupPtr);
374PRINT("[OK]\n");
375}
376
377// free table backups if any
378sModeTable * table = map->modeTables;
379while (table != NULL)
380{
381if (table->backup != NULL)
382{
383PRINT("Table #%d: Freeing backup\t", table->id);
384FREE(table->backup);
385PRINT("[OK]\n");
386}
387
388if (table != NULL)
389{
390PRINT("Table #%d: Freeing\t\t", table->id);
391FREE(table);
392PRINT("[OK]\n");
393}
394
395if (table->next == NULL)
396break;
397
398table = table->next;
399}
400
401PRINT("Freeing map\t\t\t");
402FREE(map);
403PRINT("[OK]\n");
404}
405
406void unlockVbios(vBiosMap * map)
407{
408
409map->unlocked = true;
410
411switch (map->chipset)
412{
413case CT_UNKWN:
414break;
415case CT_830:
416case CT_855GM:
417outl(0xcf8, 0x8000005a);
418map->b1 = inb(0xcfe);
419
420outl(0xcf8, 0x8000005a);
421outb(0xcfe, 0x33);
422break;
423case CT_845G:
424case CT_865G:
425case CT_915G:
426case CT_915GM:
427case CT_945G:
428case CT_945GM:
429case CT_945GME:
430case CT_946GZ:
431case CT_955X:
432case CT_G965:
433case CT_Q965:
434case CT_965GM:
435case CT_975X:
436case CT_P35:
437case CT_X48:
438case CT_B43:
439case CT_Q45:
440case CT_P45:
441case CT_GM45:
442case CT_G41:
443case CT_G31:
444case CT_G45:
445case CT_500:
446
447outl(0xcf8, 0x80000090);
448map->b1 = inb(0xcfd);
449map->b2 = inb(0xcfe);
450outl(0xcf8, 0x80000090);
451outb(0xcfd, 0x33);
452outb(0xcfe, 0x33);
453break;
454}
455
456#if DEBUG
457{
458uint32_t t = inl(0xcfc);
459PRINT("unlock PAM: (0x%08x)\n", t);
460}
461#endif
462}
463
464void relockVbios(vBiosMap * map)
465{
466
467map->unlocked = false;
468
469switch (map->chipset)
470{
471case CT_UNKWN:
472break;
473case CT_830:
474case CT_855GM:
475outl(0xcf8, 0x8000005a);
476outb(0xcfe, map->b1);
477break;
478case CT_845G:
479case CT_865G:
480case CT_915G:
481case CT_915GM:
482case CT_945G:
483case CT_945GM:
484case CT_945GME:
485case CT_946GZ:
486case CT_955X:
487case CT_G965:
488case CT_Q965:
489case CT_965GM:
490case CT_975X:
491case CT_P35:
492case CT_X48:
493case CT_B43:
494case CT_Q45:
495case CT_P45:
496case CT_GM45:
497case CT_G41:
498case CT_G31:
499case CT_G45:
500case CT_500:
501
502outl(0xcf8, 0x80000090);
503outb(0xcfd, map->b1);
504outb(0xcfe, map->b2);
505break;
506}
507
508#if DEBUG
509{
510 uint32_t t = inl(0xcfc);
511PRINT("relock PAM: (0x%08x)\n", t);
512}
513#endif
514}
515
516/*
517 * saveVbios - save the entire vBios in case the patch has to be removed
518 * Azi: only on Intel??
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//verbose("Table/s restored...\n");
567}
568relockVbios(map);
569}
570
571/*
572 * patchVbios - call the vendor specific function to patch the VESA tables
573 * x & y are horizontal and vertical dimensions respectively, in pixels
574 * for GMA and ATI, only first mode in Table is patched
575 *
576 * each vendor specific function have the same form :
577 * bool vendorSetMode_type(sModeTable * table, uint8_t index, uint32_t * x, uint32_t * y);
578 * where 'table' is the VESA table to patch, 'index' is the index of the mode in table,
579 * 'x' & 'y' are pointer to the target resolution and return the next resolution in table.
580 */
581void patchVbios(vBiosMap * map, uint32_t x, uint32_t y, uint32_t bp, uint32_t hTotal, uint32_t vTotal)
582{
583uint32_t i = 0;
584
585sModeTable * table = map->modeTables;
586
587// save the target resolution for future use
588map->currentX = x;
589map->currentY = y;
590
591unlockVbios(map);
592
593// Get the aspect ratio for the requested mode
594getAspectRatio(&map->aspectRatio, x, y);
595
596i = 0;
597
598// Call the vendor specific function for each available VESA Table
599table = map->modeTables;
600while (table != NULL)
601{
602//reset resolution value before treating a new table
603x = map->currentX;
604y = map->currentY;
605
606PRINT("Patching Table #%d: \n", table->id);
607
608map->setMode(table, i, &x, &y);
609#ifdef AUTORES_DEBUG
610pause();
611#endif
612
613table = table->next;
614}
615
616relockVbios(map);
617return;
618}
619/*
620void patchRes()
621{
622//UInt32 paramsAR[4];
623paramsAR[3] = 0;
624
625// Open the VBios and store VBios or Tables
626map = openVbios(CT_UNKWN);
627
628//Get Resolution from Graphics Mode key...
629int count = getNumberArrayFromProperty(kGraphicsModeKey, paramsAR, 4);
630
631// ... or EDID.
632if (count < 3)
633{
634getResolution(paramsAR);
635// check the DEBUG stuff... also on TEXT MODE (this is not printing).
636PRINT("Resolution: %dx%d (EDID)\n",paramsAR[0], paramsAR[1]);
637}
638else
639{
640PRINT("Resolution: %dx%d (Graphics Mode key)\n",paramsAR[0], paramsAR[1]);
641
642if ( paramsAR[2] == 256 ) paramsAR[2] = 8;
643if ( paramsAR[2] == 555 ) paramsAR[2] = 16;
644if ( paramsAR[2] == 888 ) paramsAR[2] = 32;
645}
646
647// If using GUI, patch the video bios with the extracted resolution,
648// before initGui.
649
650// perfom the actual VBIOS patching
651if (paramsAR[0] != 0 && paramsAR[1] != 0)
652{
653patchVbios(map, paramsAR[0], paramsAR[1], paramsAR[2], 0, 0);
654}
655
656closeVbios(map);
657//Azi: gAutoResolution was just set to false on closeVbios().
658gAutoResolution = true;
659
660if (bootArgs->Video.v_display == VGA_TEXT_MODE)
661{
662gui.screen.width = paramsAR[0];
663gui.screen.height = paramsAR[1];
664}
665
666// If the patch is working properly, we're done. If not and it's just a matter
667// of wrong resolution, we can try reapply the patch; see "case kF2Key:", options.c.
668
669// The patch works properly but we're not using GUI; keep Vbios open and patch/close
670// on drawBootGraphics().
671// ??????Don't forget we´re maybe using this to get correct resolution after login,
672// despite having qe/ci or not...!!!!
673}
674
675void reloadRes()
676{
677//UInt32 paramsAR[4];
678paramsAR[3] = 0;
679
680map = openVbios(CT_UNKWN);
681// Has the target Resolution Changed ?
682int count = getNumberArrayFromProperty(kGraphicsModeKey, paramsAR, 4);
683
684if ( count < 3 ) // why this? we are implicitly trying to change the resolution
685// at boot prompt, using Graphics Mode flag...
686{
687getResolution(paramsAR);
688}
689else
690{
691if ( paramsAR[2] == 256 ) paramsAR[2] = 8;
692if ( paramsAR[2] == 555 ) paramsAR[2] = 16;
693if ( paramsAR[2] == 888 ) paramsAR[2] = 32;
694}
695
696// user changed resolution...
697if ((paramsAR[0] != 0) && (paramsAR[1] != 0) &&
698(paramsAR[0] != map->currentX) && (paramsAR[1] != map->currentY))
699{
700//Azi: same shit as "case kTabKey:" - check
701// Go back to TEXT mode while we change the mode
702if (bootArgs->Video.v_display == GRAPHICS_MODE)
703{
704CursorState cursorState;
705
706setVideoMode(VGA_TEXT_MODE, 0);
707
708setCursorPosition(0, 0, 0);
709clearScreenRows(0, kScreenLastRow);
710changeCursor( 0, 0, kCursorTypeHidden, &cursorState );
711
712// Reapply patch
713patchVbios(map, paramsAR[0], paramsAR[1], paramsAR[2], 0, 0);
714
715if (useGUI && (gui.initialised == true))
716initGUI();
717// Make sure all values are set
718if (bootArgs->Video.v_display != GRAPHICS_MODE)
719bootArgs->Video.v_display = GRAPHICS_MODE;
720
721if (!useGUI)
722useGUI = true;
723
724// redraw the background buffer
725drawBackground();
726gui.devicelist.draw = true;
727gui.redraw = true;
728
729if (showBootBanner)
730{
731// Display banner and show hardware info.
732gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
733}
734
735// redraw background
736memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels,
737 gui.backbuffer->width * gui.backbuffer->height * 4);
738
739nextRow = kMenuTopRow;
740showPrompt = true;
741
742if (gDeviceCount)
743{
744showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
745nextRow += min( gDeviceCount, kMenuMaxItems ) + 3;
746}
747
748// Show the boot prompt.
749showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
750showBootPrompt( nextRow, showPrompt );
751
752// this is used to avoid resetting the incorrect mode while quiting the boot menu
753//map->hasSwitched = true;
754}
755}
756
757closeVbios(map);
758//Azi: gAutoResolution was just set to false on closeVbios.
759gAutoResolution = true;
760}*/
761

Archive Download this file

Revision: 602