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//------------
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:reminder
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//make sure to turn autoResolution off
368if (gAutoResolution == true)
369gAutoResolution = false;
370
371// if we saved the vBios, free the copy
372if (map->biosBackupPtr != NULL)
373{
374PRINT("Freeing biosBackupPtr\t");
375FREE(map->biosBackupPtr);
376PRINT("[OK]\n");
377}
378
379// free table backups if any
380sModeTable * table = map->modeTables;
381while (table != NULL)
382{
383if (table->backup != NULL)
384{
385PRINT("Table #%d: Freeing backup\t", table->id);
386FREE(table->backup);
387PRINT("[OK]\n");
388}
389
390if (table != NULL)
391{
392PRINT("Table #%d: Freeing\t\t", table->id);
393FREE(table);
394PRINT("[OK]\n");
395}
396
397if (table->next == NULL)
398break;
399
400table = table->next;
401}
402
403PRINT("Freeing map\t\t\t");
404FREE(map);
405PRINT("[OK]\n");
406}
407
408void unlockVbios(vBiosMap * map)
409{
410
411map->unlocked = true;
412
413switch (map->chipset)
414{
415case CT_UNKWN:
416break;
417case CT_830:
418case CT_855GM:
419outl(0xcf8, 0x8000005a);
420map->b1 = inb(0xcfe);
421
422outl(0xcf8, 0x8000005a);
423outb(0xcfe, 0x33);
424break;
425case CT_845G:
426case CT_865G:
427case CT_915G:
428case CT_915GM:
429case CT_945G:
430case CT_945GM:
431case CT_945GME:
432case CT_946GZ:
433case CT_955X:
434case CT_G965:
435case CT_Q965:
436case CT_965GM:
437case CT_975X:
438case CT_P35:
439case CT_X48:
440case CT_B43:
441case CT_Q45:
442case CT_P45:
443case CT_GM45:
444case CT_G41:
445case CT_G31:
446case CT_G45:
447case CT_500:
448
449outl(0xcf8, 0x80000090);
450map->b1 = inb(0xcfd);
451map->b2 = inb(0xcfe);
452outl(0xcf8, 0x80000090);
453outb(0xcfd, 0x33);
454outb(0xcfe, 0x33);
455break;
456}
457
458#if DEBUG
459{
460uint32_t t = inl(0xcfc);
461PRINT("unlock PAM: (0x%08x)\n", t);
462}
463#endif
464}
465
466void relockVbios(vBiosMap * map)
467{
468
469map->unlocked = false;
470
471switch (map->chipset)
472{
473case CT_UNKWN:
474break;
475case CT_830:
476case CT_855GM:
477outl(0xcf8, 0x8000005a);
478outb(0xcfe, map->b1);
479break;
480case CT_845G:
481case CT_865G:
482case CT_915G:
483case CT_915GM:
484case CT_945G:
485case CT_945GM:
486case CT_945GME:
487case CT_946GZ:
488case CT_955X:
489case CT_G965:
490case CT_Q965:
491case CT_965GM:
492case CT_975X:
493case CT_P35:
494case CT_X48:
495case CT_B43:
496case CT_Q45:
497case CT_P45:
498case CT_GM45:
499case CT_G41:
500case CT_G31:
501case CT_G45:
502case CT_500:
503
504outl(0xcf8, 0x80000090);
505outb(0xcfd, map->b1);
506outb(0xcfe, map->b2);
507break;
508}
509
510#if DEBUG
511{
512 uint32_t t = inl(0xcfc);
513PRINT("relock PAM: (0x%08x)\n", t);
514}
515#endif
516}
517
518/*
519 * saveVbios - save the entire vBios in case the patch has to be removed
520 * Azi: only on Intel??
521 */
522void saveVbios(vBiosMap * map)
523{
524map->biosBackupPtr = malloc(VBIOS_SIZE);
525bcopy((const uint8_t *)0xC0000, map->biosBackupPtr, VBIOS_SIZE);
526}
527
528/*
529 * restoreVbios - restore the vBios backup or table backups if any
530 */
531void restoreVbios(vBiosMap * map)
532{
533if ((map->bios == BT_ATI_1) || (map->bios == BT_ATI_2) || (map->bios == BT_NVDA))
534{
535restoreTables(map, map->modeTables);
536}
537else
538{
539unlockVbios(map);
540bcopy(map->biosBackupPtr,(uint8_t *)0xC0000, VBIOS_SIZE);
541relockVbios(map);
542}
543}
544
545/*
546 * saveTables - save the tables in case the patch has to be removed
547 */
548void saveTables(sModeTable * table)
549{
550while (table != NULL)
551{
552table->backup = (uint8_t *)malloc(table->size);
553bcopy((const uint8_t *)table->pointer, table->backup, table->size);
554table = table->next;
555}
556}
557
558/*
559 * restoreTables - restore tables backup
560 */
561void restoreTables(vBiosMap * map, sModeTable * table)
562{
563unlockVbios(map);
564while (table != NULL)
565{
566bcopy(table->backup, (uint8_t *)table->pointer, table->size);
567table = table->next;
568verbose("Restoring table/s for patch cancelation\n");
569}
570relockVbios(map);
571}
572
573/*
574 * patchVbios - call the vendor specific function to patch the VESA tables
575 * x & y are horizontal and vertical dimensions respectively, in pixels
576 * for GMA and ATI, only first mode in Table is patched
577 *
578 * each vendor specific function have the same form :
579 * bool vendorSetMode_type(sModeTable * table, uint8_t index, uint32_t * x, uint32_t * y);
580 * where 'table' is the VESA table to patch, 'index' is the index of the mode in table,
581 * 'x' & 'y' are pointer to the target resolution and return the next resolution in table.
582 */
583void patchVbios(vBiosMap * map, uint32_t x, uint32_t y, uint32_t bp, uint32_t hTotal, uint32_t vTotal)
584{
585uint32_t i = 0;
586
587sModeTable * table = map->modeTables;
588
589// save the target resolution for future use
590map->currentX = x;
591map->currentY = y;
592
593unlockVbios(map);
594
595// Get the aspect ratio for the requested mode
596getAspectRatio(&map->aspectRatio, x, y);
597
598i = 0;
599
600// Call the vendor specific function for each available VESA Table
601table = map->modeTables;
602while (table != NULL)
603{
604//reset resolution value before treating a new table
605x = map->currentX;
606y = map->currentY;
607
608PRINT("Patching Table #%d: \n", table->id);
609
610map->setMode(table, i, &x, &y);
611#ifdef AUTORES_DEBUG
612pause();
613#endif
614
615table = table->next;
616}
617
618relockVbios(map);
619return;
620}
621
622void startAutoRes()
623{
624//UInt32 paramsAR[4];
625paramsAR[3] = 0;
626
627// Open the Vbios and store Vbios or Tables
628map = openVbios(CT_UNKWN);
629
630//Get resolution from Graphics Mode key...
631int count = getNumberArrayFromProperty(kGraphicsModeKey, paramsAR, 4);
632
633// ... or EDID.
634if (count < 3)
635{
636getResolution(paramsAR);
637// check the DEBUG stuff... also on TEXT MODE (this is not printing).
638PRINT("Resolution: %dx%d (EDID)\n",paramsAR[0], paramsAR[1]);
639}
640else
641{
642PRINT("Resolution: %dx%d (Graphics Mode key)\n",paramsAR[0], paramsAR[1]);
643
644if ( paramsAR[2] == 256 ) paramsAR[2] = 8;
645if ( paramsAR[2] == 555 ) paramsAR[2] = 16;
646if ( paramsAR[2] == 888 ) paramsAR[2] = 32;
647}
648
649// perfom the actual Vbios patching
650if (paramsAR[0] != 0 && paramsAR[1] != 0)
651{
652patchVbios(map, paramsAR[0], paramsAR[1], paramsAR[2], 0, 0);
653}
654
655//Azi: passing resolution for TEXT MODE "verbose" boot. (check again later!)
656if (bootArgs->Video.v_display == VGA_TEXT_MODE)
657{
658gui.screen.width = paramsAR[0];
659gui.screen.height = paramsAR[1];
660}
661
662// If the patch is working properly, we're done. If not and it's just a matter
663// of wrong resolution, we can try reapply the patch; see "case kF2Key:", options.c.
664}
665
666void reloadAutoRes()
667{
668extern int key;
669extern int nextRow;
670extern BVRef menuBVR;
671extern bool showPrompt;
672
673extern bool showBootBanner;
674extern MenuItem * menuItems;
675extern int selectIndex;
676
677extern void showMenu( const MenuItem * items, int count, int selection, int row, int height );
678extern void showBootPrompt(int row, bool visible);
679extern void clearBootArgs(void);
680extern void changeCursor( int col, int row, int type, CursorState * cs );
681
682if ((gAutoResolution == true) && useGUI && map )
683{
684// get the new Graphics Mode key
685processBootOptions(); //Azi: use processBootArgument instead?
686
687//UInt32 paramsAR[4];
688paramsAR[3] = 0;
689
690getNumberArrayFromProperty(kGraphicsModeKey, paramsAR, 4);
691
692// user changed resolution...
693if ((paramsAR[0] != 0) && (paramsAR[1] != 0) &&
694(paramsAR[0] != map->currentX) && (paramsAR[1] != map->currentY))
695{
696//Azi: identical to "case kTabKey:"(check later)
697if (bootArgs->Video.v_display == GRAPHICS_MODE)
698{
699CursorState cursorState;
700
701// Go back to TEXT MODE while we change the mode
702setVideoMode(VGA_TEXT_MODE, 0);
703
704setCursorPosition(0, 0, 0);
705clearScreenRows(0, kScreenLastRow);
706changeCursor( 0, 0, kCursorTypeHidden, &cursorState );
707
708// Reapply patch
709patchVbios(map, paramsAR[0], paramsAR[1], paramsAR[2], 0, 0);
710
711if (useGUI && (gui.initialised == true))
712initGUI();
713// Make sure all values are set
714if (bootArgs->Video.v_display != GRAPHICS_MODE)
715bootArgs->Video.v_display = GRAPHICS_MODE;
716
717if (!useGUI)
718useGUI = true;
719
720// redraw the background buffer
721drawBackground();
722gui.devicelist.draw = true;
723gui.redraw = true;
724
725if (showBootBanner)
726{
727// Display banner and show hardware info.
728gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
729}
730
731// redraw background
732memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels,
733 gui.backbuffer->width * gui.backbuffer->height * 4);
734
735nextRow = kMenuTopRow;
736showPrompt = true;
737
738if (gDeviceCount)
739{
740showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
741nextRow += MIN( gDeviceCount, kMenuMaxItems ) + 3;
742}
743
744// Show the boot prompt.
745showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
746showBootPrompt( nextRow, showPrompt );
747
748// this is used to avoid resetting the incorrect mode while quiting the boot menu
749//map->hasSwitched = true; (check again later!)
750}
751}
752
753clearBootArgs();
754key = 0;
755}
756else // if gAutoResolution == false...
757{
758// ... do "nothing".(Reviewing...)
759clearBootArgs();
760key = 0;
761}
762}
763
764void endAutoRes()
765{
766// Restore and close Vbios for patch cancelation.
767if ((gAutoResolution == false) && map)
768{
769restoreVbios(map);
770closeVbios(map);
771
772//Azi: closing Vbios here without restoring it as above, causes an allocation error,
773// if the user tries to boot, after a e.g."Can't find bla_kernel" msg.
774// Doing it on execKernel() instead.
775}
776
777//Azi: while testing i didn't got any problems booting without closing Vbios...
778// closing it just in case. (check again later!)
779if ((gAutoResolution == true) && map)
780{
781closeVbios(map);
782
783// gAutoResolution was just set to false on closeVbios().
784// We need to be "true" for drawBootGraphics().
785gAutoResolution = true;
786}
787}
788
789
790

Archive Download this file

Revision: 621