Index: branches/azimutz/Chazi/i386/libsaio/ati_resolution.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/ati_resolution.c (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/ati_resolution.c (revision 465) @@ -0,0 +1,104 @@ +/* + * ati_resolution.c + * + * + * Created by Le Bidou on 19/03/10. + * Copyright 2010 ---. All rights reserved. + * + */ + +#include "ati_resolution.h" + +char detectAtiBiosType(sModeTable * table) { + return table->size % sizeof(atomModeTiming) == 0; +} + + + +vBiosMap * openAtiVbios(vBiosMap * map, atiBiosTables atiTables) +{ + /* + * Locate the Standard VESA Table + */ + + atiTables.masterDataTables = (uint16_t *) &((atomMasterDataTable *) (map->biosPtr + atiTables.atomRomHeader->masterDataTableOffset))->listOfDataTables; + uint16_t stdVesaOffset = (uint16_t) ((atomMasterListOfDataTables *)atiTables.masterDataTables)->StandardVESA_Timing; + atomStandardVesaTiming * stdVesa = (atomStandardVesaTiming *) (map->biosPtr + stdVesaOffset); + + // intialize the table chain with one element + sModeTable * table = intializeTables(map, 1); + + table->pointer = (uint8_t *)stdVesa + sizeof(atomCommonTableHeader); + PRINT("Standard VESA Table at offset * 0x%x\n", (uint8_t)(table->pointer - map->biosPtr)); + if (table->pointer == 0) { + PRINT("Unable to locate the mode table.\n"); + PRINT("Please run the program 'dump_bios' as root and\n"); + PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n"); + + closeVbios(map); + return 0; + } + + //Determine Size of the Table + table->size = stdVesa->header.structureSize - sizeof(atomCommonTableHeader); + + /* + * Find out type of table and how many entries it has + */ + + if (!detectAtiBiosType(table)) map->bios = BT_ATI_2; + if (map->bios == BT_ATI_2) { + table->modeCount = table->size / sizeof(atomDtdFormat); + map->setMode = atiSetMode_2; + PRINT("Using DTD Format modelines\n"); + } else { + table->modeCount = table->size / sizeof(atomModeTiming); + map->setMode = atiSetMode_1; + PRINT("Using Atom Mode Timing modelines\n"); + } + saveTables(table); + return map; +} + +bool atiSetMode_1(sModeTable * table, uint8_t idx, uint32_t * x, uint32_t * y) +{ + atomModeTiming *modeTiming = (atomModeTiming *) table->pointer; + + // patch only if mode differs + if ((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive)) { + PRINT("Mode %dx%d -> ",modeTiming[idx].hActive, modeTiming[idx].vActive); + + modeTiming[idx].hActive = *x; + modeTiming[idx].vActive = *y; + + PRINT("%dx%d\n",modeTiming[idx].hActive, modeTiming[idx].vActive); + } + + // since only the first mode in table is patched, this is deprecated + *x = modeTiming[idx + 1].hActive; + *y = modeTiming[idx + 1].vActive; + + return TRUE; +} + +bool atiSetMode_2(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y) +{ + atomDtdFormat *modeTiming = (atomDtdFormat *) table->pointer; + + // patch only if mode differs + if ((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive)) { + + PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive); + + modeTiming[idx].hActive = *x; + modeTiming[idx].vActive = *y; + + PRINT("%dx%d\n", modeTiming[idx].hActive, modeTiming[idx].vActive); + } + + // since only the first mode in table is patched, this is deprecated + *x = modeTiming[idx + 1].hActive; + *y = modeTiming[idx + 1].hActive; + + return TRUE; +} Index: branches/azimutz/Chazi/i386/libsaio/ati_resolution.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/ati_resolution.h (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/ati_resolution.h (revision 465) @@ -0,0 +1,197 @@ +/* + * ati_resolution.h + * + * + * Created by Le Bidou on 19/03/10. + * Copyright 2010 ---. All rights reserved. + * + */ + +#ifndef _ATI_RESOLUTION_H_ +#define _ATI_RESOLUTION_H_ + +#include "libsaio.h" +#include "autoresolution.h" + +#define ATI_SIGNATURE1 "ATI MOBILITY RADEON" +#define ATI_SIGNATURE2 "ATI Technologies Inc" + +/****************************************************************************/ +/*Shortatombios.h parts: */ +/*Portion I: Definitions shared between VBIOS and Driver */ +/****************************************************************************/ + + +#define ATOM_VERSION_MAJOR 0x00020000 +#define ATOM_VERSION_MINOR 0x00000002 + +#define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR) + +#pragma pack(1) /* BIOS data must use byte aligment */ + +/* Define offset to location of ROM header. */ + +#define OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER 0x00000048L +#define OFFSET_TO_ATOM_ROM_IMAGE_SIZE 0x00000002L + +typedef struct +{ + uint16_t structureSize; + uint8_t TableFormatRevision; /*Change it when the Parser is not backward compatible */ + uint8_t TableContentRevision; /*Change it only when the table needs to change but the firmware */ + /*Image can't be updated, while Driver needs to carry the new table! */ +}atomCommonTableHeader; + +typedef struct +{ + atomCommonTableHeader sHeader; + uint8_t firmWareSignature[4]; /*Signature to distinguish between Atombios and non-atombios, + atombios should init it as "ATOM", don't change the position */ + uint16_t biosRuntimeSegmentAddress; + uint16_t protectedModeInfoOffset; + uint16_t configFilenameOffset; + uint16_t cRcBlockOffset; + uint16_t BiosBootupMessageOffset; + uint16_t int10Offset; + uint16_t pciBusDevInitCode; + uint16_t ioBaseAddress; + uint16_t subsystemVendorID; + uint16_t subsystemID; + uint16_t pciInfoOffset; + uint16_t masterCommandTableOffset; /*Offset for SW to get all command table offsets, Don't change the position */ + uint16_t masterDataTableOffset; /*Offset for SW to get all data table offsets, Don't change the position */ + uint8_t extendedFunctionCode; + uint8_t reserved; +}atomRomHeader; + +/****************************************************************************/ +// Structure used in Data.mtb +/****************************************************************************/ +typedef struct +{ + uint16_t UtilityPipeLine; // Offest for the utility to get parser info,Don't change this position! + uint16_t MultimediaCapabilityInfo; // Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios + uint16_t MultimediaConfigInfo; // Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios + uint16_t StandardVESA_Timing; // Only used by Bios + uint16_t FirmwareInfo; // Shared by various SW components,latest version 1.4 + uint16_t DAC_Info; // Will be obsolete from R600 + uint16_t LVDS_Info; // Shared by various SW components,latest version 1.1 + uint16_t TMDS_Info; // Will be obsolete from R600 + uint16_t AnalogTV_Info; // Shared by various SW components,latest version 1.1 + uint16_t SupportedDevicesInfo; // Will be obsolete from R600 + uint16_t GPIO_I2C_Info; // Shared by various SW components,latest version 1.2 will be used from R600 + uint16_t VRAM_UsageByFirmware; // Shared by various SW components,latest version 1.3 will be used from R600 + uint16_t GPIO_Pin_LUT; // Shared by various SW components,latest version 1.1 + uint16_t VESA_ToInternalModeLUT; // Only used by Bios + uint16_t ComponentVideoInfo; // Shared by various SW components,latest version 2.1 will be used from R600 + uint16_t PowerPlayInfo; // Shared by various SW components,latest version 2.1,new design from R600 + uint16_t CompassionateData; // Will be obsolete from R600 + uint16_t SaveRestoreInfo; // Only used by Bios + uint16_t PPLL_SS_Info; // Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info + uint16_t OemInfo; // Defined and used by external SW, should be obsolete soon + uint16_t XTMDS_Info; // Will be obsolete from R600 + uint16_t MclkSS_Info; // Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used + uint16_t Object_Header; // Shared by various SW components,latest version 1.1 + uint16_t IndirectIOAccess; // Only used by Bios,this table position can't change at all!! + uint16_t MC_InitParameter; // Only used by command table + uint16_t ASIC_VDDC_Info; // Will be obsolete from R600 + uint16_t ASIC_InternalSS_Info; // New tabel name from R600, used to be called "ASIC_MVDDC_Info" + uint16_t TV_VideoMode; // Only used by command table + uint16_t VRAM_Info; // Only used by command table, latest version 1.3 + uint16_t MemoryTrainingInfo; // Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 + uint16_t IntegratedSystemInfo; // Shared by various SW components + uint16_t ASIC_ProfilingInfo; // New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 + uint16_t VoltageObjectInfo; // Shared by various SW components, latest version 1.1 + uint16_t PowerSourceInfo; // Shared by various SW components, latest versoin 1.1 +}atomMasterListOfDataTables; + +typedef struct +{ + atomCommonTableHeader header; + atomMasterListOfDataTables listOfDataTables; +}atomMasterDataTable; + +typedef union +{ + uint16_t usAccess; +}atomModeMiscInfoAccess; + +/****************************************************************************/ +// Structure used in StandardVESA_TimingTable +// AnalogTV_InfoTable +// ComponentVideoInfoTable +/****************************************************************************/ +typedef struct +{ + uint16_t hTotal; + uint16_t hActive; + uint16_t hSyncStart; + uint16_t hSyncWidth; + uint16_t vTotal; + uint16_t vActive; + uint16_t vSyncStart; + uint16_t vSyncWidth; + uint16_t pixelClock; //in 10Khz unit + atomModeMiscInfoAccess modeMiscInfo; + uint16_t overscanRight; + uint16_t overscanLeft; + uint16_t overscanBottom; + uint16_t overscanTop; + uint16_t teserve; + uint8_t internalModeNumber; + uint8_t refreshRate; +}atomModeTiming; + +typedef struct +{ + uint16_t pixelClock; + uint16_t hActive; + uint16_t hBlank; + uint16_t vActive; + uint16_t vBlank; + uint16_t hSyncOffset; + uint16_t hSyncWidth; + uint16_t vSyncOffset; + uint16_t vSyncWidth; + uint16_t imageHSize; + uint16_t imageVSize; + uint8_t hBorder; + uint8_t vBorder; + atomModeMiscInfoAccess modeMiscInfo; + uint8_t internalModeNumber; + uint8_t refreshRate; +}atomDtdFormat; + + +/****************************************************************************/ +/*Original ati_resolution.h parts: */ +/****************************************************************************/ + + +typedef struct +{ + atomCommonTableHeader header; + uint8_t * modeTimings; +}atomStandardVesaTiming; + + + + +typedef struct +{ + uint8_t *base; + atomRomHeader *atomRomHeader; + uint16_t *masterCommandTables; + uint16_t *masterDataTables; +} atiBiosTables; + +char detectAtiBiosType(sModeTable * table); + +vBiosMap * openAtiVbios(vBiosMap * map, atiBiosTables atiTables); + +bool atiSetMode_1(sModeTable* map, uint8_t idx, uint32_t* x, uint32_t* y); +bool atiSetMode_2(sModeTable* map, uint8_t idx, uint32_t* x, uint32_t* y); + + + +#endif \ No newline at end of file Index: branches/azimutz/Chazi/i386/libsaio/Makefile =================================================================== --- branches/azimutz/Chazi/i386/libsaio/Makefile (revision 464) +++ branches/azimutz/Chazi/i386/libsaio/Makefile (revision 465) @@ -42,8 +42,10 @@ cpu.o platform.o acpi_patcher.o \ smbios_patcher.o fake_efi.o ext2fs.o \ hpet.o dram_controllers.o spd.o usb.o pci_setup.o \ - device_inject.o nvidia.o ati.o pci_root.o \ - convert.o mem.o aml_generator.o + device_inject.o nvidia.o ati.o gma.o \ + gma_resolution.o ati_resolution.o nvidia_resolution.o \ + pci_root.o convert.o mem.o aml_generator.o \ + autoresolution.o edid.o SAIO_EXTERN_OBJS = console.o Index: branches/azimutz/Chazi/i386/libsaio/gma.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/gma.c (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/gma.c (revision 465) @@ -0,0 +1,149 @@ +/* +Original patch by nawcom -> http://forum.voodooprojects.org/index.php/topic,1029.msg4427.html#msg4427 +*/ +#include "libsaio.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +#include "device_inject.h" +#include "gma.h" + +#ifndef DEBUG_GMA +#define DEBUG_GMA 0 +#endif + +#if DEBUG_GMA +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +uint8_t GMAX3100_vals[22][4] = { + { 0x01,0x00,0x00,0x00 }, + { 0x01,0x00,0x00,0x00 }, + { 0x01,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x08 }, + { 0x64,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x08 }, + { 0x01,0x00,0x00,0x00 }, + { 0x20,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 }, + { 0x01,0x00,0x00,0x00 }, + { 0x20,0x03,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 }, + { 0x08,0x52,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 }, + { 0x01,0x00,0x00,0x00 }, + { 0x01,0x00,0x00,0x00 }, + { 0x3B,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00 } +}; +uint8_t reg_TRUE[] = { 0x01 ,0x00 ,0x00 ,0x00 }; +uint8_t reg_FALSE[] = { 0x00,0x00,0x00,0x00 }; + +static struct gma_gpu_t KnownGPUS[] = { + { 0x00000000, "Unknown" }, + { 0x808627A2, "Mobile GMA950" }, + { 0x808627AE, "Mobile GMA950" }, + { 0x808627A6, "Mobile GMA950" }, + { 0x80862772, "Desktop GMA950" }, + { 0x80862776, "Desktop GMA950" }, + { 0x80862A02, "GMAX3100" }, + { 0x80862A03, "GMAX3100" }, + { 0x80862A12, "GMAX3100" }, + { 0x80862A13, "GMAX3100" }, +}; + +char *get_gma_model(uint32_t id) { + int i=0; + for(i = 0; i < (sizeof(KnownGPUS) / sizeof(KnownGPUS[0])); i++) { + if(KnownGPUS[i].device == id) + return KnownGPUS[i].name; + } + return KnownGPUS[0].name; +} + +bool setup_gma_devprop(pci_dt_t *gma_dev) +{ + //int len; + char *devicepath; + volatile uint8_t *regs; + uint32_t bar[7]; + char *model; + uint8_t BuiltIn = 0x00; + uint8_t ClassFix[4] = { 0x00, 0x00, 0x03, 0x00 }; + + devicepath = get_pci_dev_path(gma_dev); + + bar[0] = pci_config_read32(gma_dev->dev.addr, 0x10); + regs = (uint8_t *) (bar[0] & ~0x0f); + + model = get_gma_model((gma_dev->vendor_id << 16) | gma_dev->device_id); + + verbose("Intel %s [%04x:%04x] :: %s\n", + model, gma_dev->vendor_id, gma_dev->device_id, devicepath); + + if (!string) + string = devprop_create_string(); + struct DevPropDevice *device = malloc(sizeof(struct DevPropDevice)); + device = devprop_add_device(string, devicepath); + + if(!device) + { + printf("Failed initializing dev-prop string dev-entry, press any key...\n"); + + getc(); + return false; + } + + devprop_add_value(device, "model", (uint8_t*)model, (strlen(model) + 1)); + devprop_add_value(device, "device_type", (uint8_t*)"display", 8); + + if (model == (char *)"Mobile GMA950") { + devprop_add_value(device, "AAPL,HasPanel", reg_TRUE, 4); + devprop_add_value(device, "built-in", &BuiltIn, 1); + devprop_add_value(device, "class-code", ClassFix, 4); + } else if (model == (char *)"Desktop GMA950") { + BuiltIn = 0x01; + devprop_add_value(device, "built-in", &BuiltIn, 1); + } else if (model == (char *)"GMAX3100") { + devprop_add_value(device, "AAPL,HasPanel",GMAX3100_vals[0], 4); + devprop_add_value(device, "AAPL,SelfRefreshSupported",GMAX3100_vals[1], 4); + devprop_add_value(device, "AAPL,aux-power-connected",GMAX3100_vals[2], 4); + devprop_add_value(device, "AAPL,backlight-control",GMAX3100_vals[3], 4); + devprop_add_value(device, "AAPL00,blackscreen-preferences",GMAX3100_vals[4], 4); + devprop_add_value(device, "AAPL01,BacklightIntensity",GMAX3100_vals[5], 4); + devprop_add_value(device, "AAPL01,blackscreen-preferences",GMAX3100_vals[6], 4); + devprop_add_value(device, "AAPL01,DataJustify",GMAX3100_vals[7], 4); + devprop_add_value(device, "AAPL01,Depth",GMAX3100_vals[8], 4); + devprop_add_value(device, "AAPL01,Dither",GMAX3100_vals[9], 4); + devprop_add_value(device, "AAPL01,DualLink",GMAX3100_vals[10], 4); + devprop_add_value(device, "AAPL01,Height",GMAX3100_vals[11], 4); + devprop_add_value(device, "AAPL01,Interlace",GMAX3100_vals[12], 4); + devprop_add_value(device, "AAPL01,Inverter",GMAX3100_vals[13], 4); + devprop_add_value(device, "AAPL01,InverterCurrent",GMAX3100_vals[14], 4); + devprop_add_value(device, "AAPL01,InverterCurrency",GMAX3100_vals[15], 4); + devprop_add_value(device, "AAPL01,LinkFormat",GMAX3100_vals[16], 4); + devprop_add_value(device, "AAPL01,LinkType",GMAX3100_vals[17], 4); + devprop_add_value(device, "AAPL01,Pipe",GMAX3100_vals[18], 4); + devprop_add_value(device, "AAPL01,PixelFormat",GMAX3100_vals[19], 4); + devprop_add_value(device, "AAPL01,Refresh",GMAX3100_vals[20], 4); + devprop_add_value(device, "AAPL01,Stretch",GMAX3100_vals[21], 4); + } + + stringdata = malloc(sizeof(uint8_t) * string->length); + if(!stringdata) + { + printf("no stringdata press a key...\n"); + getc(); + return false; + } + + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + + return true; +} Index: branches/azimutz/Chazi/i386/libsaio/gma.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/gma.h (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/gma.h (revision 465) @@ -0,0 +1,16 @@ +#ifndef __LIBSAIO_GMA_H +#define __LIBSAIO_GMA_H + +bool setup_gma_devprop(pci_dt_t *gma_dev); + +struct gma_gpu_t { + unsigned device; + char *name; +}; + +#define REG8(reg) ((volatile uint8_t *)regs)[(reg)] +#define REG16(reg) ((volatile uint16_t *)regs)[(reg) >> 1] +#define REG32(reg) ((volatile uint32_t *)regs)[(reg) >> 2] + + +#endif /* !__LIBSAIO_GMA_H */ Index: branches/azimutz/Chazi/i386/libsaio/autoresolution.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/autoresolution.c (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/autoresolution.c (revision 465) @@ -0,0 +1,615 @@ + +/* Copied from 915 resolution created by steve tomljenovic + * + * This code is based on the techniques used in : + * + * - 855patch. Many thanks to Christian Zietz (czietz gmx net) + * for demonstrating how to shadow the VBIOS into system RAM + * and then modify it. + * + * - 1280patch by Andrew Tipton (andrewtipton null li). + * + * - 855resolution by Alain Poirier + * + * This source code is into the public domain. + */ + +#include "libsaio.h" +#include "autoresolution.h" +#include "nvidia_resolution.h" +#include "ati_resolution.h" +#include "gma_resolution.h" +#include "../boot2/graphics.h" + +char * chipsetTypeNames[] = { + "UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME", + "946GZ", "955X", "G965", "Q965", "965GM", "975X", + "P35", "X48", "B43", "Q45", "P45", "GM45", "G41", "G31", "G45", "500" +}; + +uint32_t getChipsetId(void) +{ + outl(0xcf8, 0x80000000); + return inl(0xcfc); +} + +chipsetType getChipset(uint32_t id) +{ + chipsetType type; + + switch (id) + { + case 0x35758086: + type = CT_830; + break; + + case 0x25608086: + type = CT_845G; + break; + + case 0x35808086: + type = CT_855GM; + break; + + case 0x25708086: + type = CT_865G; + break; + + case 0x25808086: + type = CT_915G; + break; + + case 0x25908086: + type = CT_915GM; + break; + + case 0x27708086: + type = CT_945G; + break; + + case 0x27748086: + type = CT_955X; + break; + + case 0x277c8086: + type = CT_975X; + break; + + case 0x27a08086: + type = CT_945GM; + break; + + case 0x27ac8086: + type = CT_945GME; + break; + + case 0x29708086: + type = CT_946GZ; + break; + + case 0x29a08086: + type = CT_G965; + break; + + case 0x29908086: + type = CT_Q965; + break; + + case 0x2a008086: + type = CT_965GM; + break; + + case 0x29e08086: + type = CT_X48; + break; + + case 0x2a408086: + type = CT_GM45; + break; + + case 0x2e108086: + case 0X2e908086: + type = CT_B43; + break; + + case 0x2e208086: + type = CT_P45; + break; + + case 0x2e308086: + type = CT_G41; + break; + + case 0x29c08086: + type = CT_G31; + break; + + case 0x29208086: + type = CT_G45; + break; + + case 0x81008086: + type = CT_500; + break; + + default: + type = CT_UNKWN; + break; + } + return type; +} + + +void gtfTimings(uint32_t x, uint32_t y, uint32_t freq, + uint32_t *clock, + uint16_t *hSyncStart, uint16_t *hSyncEnd, uint16_t *hBlank, + uint16_t *vSyncStart, uint16_t *vSyncEnd, uint16_t *vBlank) +{ + uint32_t hbl, vbl, vfreq; + + vbl = y + (y+1)/(20000/(11*freq) - 1) + 1; + + vfreq = vbl * freq; + hbl = 16 * (int)(x * (30 - 300000 / vfreq) / + + (70 + 300000 / vfreq) / 16 + 0); + + *vSyncStart = y; + *vSyncEnd = y + 3; + *vBlank = vbl; + *hSyncStart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 ; + *hSyncEnd = x + hbl / 2; + *hBlank = x + hbl; + *clock = (x + hbl) * vfreq / 1000; +} + + +void getAspectRatio(sAspect* aspect, uint32_t x, uint32_t y) +{ + if ((y * 16 / 9) == x) + { + aspect->width = 16; + aspect->height = 9; + } + else if ((y * 16 / 10) == x) + { + aspect->width = 16; + aspect->height = 10; + } + else if ((y * 5 / 4) == x) + { + aspect->width = 5; + aspect->height = 4; + } + else if ((y * 15 / 9) == x) + { + aspect->width = 15; + aspect->height = 9; + } + else + { + aspect->width = 4; + aspect->height = 3; + } + PRINT("Aspect Ratio is %d/%d\n", aspect->width, aspect->height); +} + + +/* + * initialize the mode tables chain + * tablesCount represents the number of VESA tables in the vBios + * return value is a pointer to the first table + */ +sModeTable * intializeTables(vBiosMap * map, int tablesCount) { + map->modeTables = (sModeTable *)malloc(sizeof(sModeTable)); + sModeTable * table = map->modeTables; + + PRINT("Creating %d Mode Tables\n", tablesCount); + + int i = tablesCount; + while ( i != 0 ) + { + table->id = tablesCount - i; + PRINT("New table with id : %d\n", table->id); + + // opening the chain if it's the first table + if (i == tablesCount) + table->prev = NULL; + else // attache the table to the chain + table->prev = table; + + //if there is more than one table, alloc the next one + if (i > 1) + { + table->next = (sModeTable *)malloc(sizeof(sModeTable)); + table = table->next; + } + else // no more table, close the chain + table->next = NULL; + + i--; + } + + return map->modeTables; +} + + +void closeVbios(vBiosMap * map); + +vBiosMap * openVbios(chipsetType forcedChipset) +{ + uint32_t z; + vBiosMap * map = NEW(vBiosMap); + + for(z = 0; z < sizeof(vBiosMap); z++) + ((char*)map)[z] = 0; + + /* + * Determine chipset + */ + + if (forcedChipset == CT_UNKWN) + { + map->chipsetId = getChipsetId(); + map->chipset = getChipset(map->chipsetId); + PRINT("Chipset is %s (pci id 0x%x)\n",chipsetTypeNames[map->chipset], map->chipsetId); + } + else if (forcedChipset != CT_UNKWN) + { + map->chipset = forcedChipset; + } + else + { + map->chipset = CT_915GM; + } + + /* + * Map the video bios to memory + */ + + map->biosPtr=(uint8_t*)VBIOS_START; + + /* + * Common initialisation + */ + + map->hasSwitched = false; + + /* + * check if we have ATI Radeon and open atombios + */ + atiBiosTables atiTables; + + atiTables.base = map->biosPtr; + atiTables.atomRomHeader = (atomRomHeader *) (map->biosPtr + *(uint16_t *) (map->biosPtr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); + + if (strcmp ((char *) atiTables.atomRomHeader->firmWareSignature, "ATOM") == 0) + { + map->bios = BT_ATI_1; + PRINT("We have an AtomBios Card\n"); + return openAtiVbios(map, atiTables); + } + + + /* + * check if we have NVidia + */ + if (map->bios != BT_ATI_1) + { + int i = 0; + while (i < 512) // we don't need to look through the whole bios, just the first 512 bytes + { + if ((map->biosPtr[i] == 'N') + && (map->biosPtr[i+1] == 'V') + && (map->biosPtr[i+2] == 'I') + && (map->biosPtr[i+3] == 'D')) + { + map->bios = BT_NVDA; + PRINT("We have an NVIDIA Card\n"); + return openNvidiaVbios(map); + break; + } + i++; + } + } + + /* + * check if we have Intel + */ + + if ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA)) + { + int i = 0; + while (i < VBIOS_SIZE) + { + if ((map->biosPtr[i] == 'I') + && (map->biosPtr[i+1] == 'n') + && (map->biosPtr[i+2] == 't') + && (map->biosPtr[i+3] == 'e') + && (map->biosPtr[i+4] == 'l')) + { + map->bios = BT_1; + PRINT("We have an Intel Card\n"); + saveVbios(map); + return openIntelVbios(map); + break; + } + i++; + } + } + + /* + * Unidentified Chipset + */ + + if ( (map->chipset == CT_UNKWN) || ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA) && (map->bios != BT_1)) ) + { + PRINT("Unknown chipset type and unrecognized bios.\n"); + + PRINT("autoresolution only works with Intel 800/900 series graphic chipsets.\n"); + + PRINT("Chipset Id: %x\n", map->chipsetId); + closeVbios(map); + return 0; + } + + /* + * Should never get there + */ + return 0; +} + +void closeVbios(vBiosMap * map) +{ + PRINT("Closing VBios\n"); + //make sure to turn autoResolution off + if (gAutoResolution == TRUE) + gAutoResolution = FALSE; + + // if we saved the vBios, free the copy + if (map->biosBackupPtr != NULL) + { + PRINT("Freeing biosBackupPtr\t"); + FREE(map->biosBackupPtr); + PRINT("[OK]\n"); + } + + // free table backups if any + sModeTable * table = map->modeTables; + while (table != NULL) + { + if (table->backup != NULL) + { + PRINT("Table #%d : Freeing backup\t", table->id); + FREE(table->backup); + PRINT("[OK]\n"); + } + + if (table != NULL) + { + PRINT("Table #%d : Freeing\t\t", table->id); + FREE(table); + PRINT("[OK]\n"); + } + + if (table->next == NULL) + break; + + table = table->next; + } + + PRINT("Freeing map\t\t\t"); + FREE(map); + PRINT("[OK]\n"); +} + +void unlockVbios(vBiosMap * map) +{ + + map->unlocked = TRUE; + + switch (map->chipset) + { + case CT_UNKWN: + break; + case CT_830: + case CT_855GM: + outl(0xcf8, 0x8000005a); + map->b1 = inb(0xcfe); + + outl(0xcf8, 0x8000005a); + outb(0xcfe, 0x33); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_955X: + case CT_G965: + case CT_Q965: + case CT_965GM: + case CT_975X: + case CT_P35: + case CT_X48: + case CT_B43: + case CT_Q45: + case CT_P45: + case CT_GM45: + case CT_G41: + case CT_G31: + case CT_G45: + case CT_500: + + outl(0xcf8, 0x80000090); + map->b1 = inb(0xcfd); + map->b2 = inb(0xcfe); + outl(0xcf8, 0x80000090); + outb(0xcfd, 0x33); + outb(0xcfe, 0x33); + break; + } + + #if DEBUG + { + uint32_t t = inl(0xcfc); + PRINT("unlock PAM: (0x%08x)\n", t); + } +#endif +} + +void relockVbios(vBiosMap * map) +{ + + map->unlocked = FALSE; + + switch (map->chipset) + { + case CT_UNKWN: + break; + case CT_830: + case CT_855GM: + outl(0xcf8, 0x8000005a); + outb(0xcfe, map->b1); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_955X: + case CT_G965: + case CT_Q965: + case CT_965GM: + case CT_975X: + case CT_P35: + case CT_X48: + case CT_B43: + case CT_Q45: + case CT_P45: + case CT_GM45: + case CT_G41: + case CT_G31: + case CT_G45: + case CT_500: + + outl(0xcf8, 0x80000090); + outb(0xcfd, map->b1); + outb(0xcfe, map->b2); + break; + } + + #if DEBUG + { + uint32_t t = inl(0xcfc); + PRINT("relock PAM: (0x%08x)\n", t); + } + #endif +} + +/* + * saveVbios - save the entire vBios in case the patch has to be removed + */ +void saveVbios(vBiosMap * map) +{ + map->biosBackupPtr = malloc(VBIOS_SIZE); + bcopy((const uint8_t *)0xC0000, map->biosBackupPtr, VBIOS_SIZE); +} + +/* + * restoreVbios - restore the vBios backup or table backups if any + */ +void restoreVbios(vBiosMap * map) +{ + if ((map->bios == BT_ATI_1) || (map->bios == BT_ATI_2) || (map->bios == BT_NVDA)) + { + restoreTables(map, map->modeTables); + } + else + { + unlockVbios(map); + bcopy(map->biosBackupPtr,(uint8_t *)0xC0000, VBIOS_SIZE); + relockVbios(map); + } +} + +/* + * saveTables - save the tables in case the patch has to be removed + */ +void saveTables(sModeTable * table) +{ + while (table != NULL) + { + table->backup = (uint8_t *)malloc(table->size); + bcopy((const uint8_t *)table->pointer, table->backup, table->size); + table = table->next; + } +} + +/* + * restoreTables - restore tables backup + */ +void restoreTables(vBiosMap * map, sModeTable * table) +{ + unlockVbios(map); + while (table != NULL) + { + bcopy(table->backup, (uint8_t *)table->pointer, table->size); + table = table->next; + } + relockVbios(map); +} + +/* + * patchVbios - call the vendor specific function to patch the VESA tables + * x & y are horizontal and vertical dimensions respectively, in pixels + * for GMA and ATI, only first mode in Table is patched + * + * each vendor specific function have the same form : + * bool vendorSetMode_type(sModeTable * table, uint8_t index, uint32_t * x, uint32_t * y); + * where 'table' is the VESA table to patch, 'index' is the index of the mode in table, + * 'x' & 'y' are pointer to the target resolution and return the next resolution in table. + */ +void patchVbios(vBiosMap * map, uint32_t x, uint32_t y, uint32_t bp, uint32_t hTotal, uint32_t vTotal) +{ + uint32_t i = 0; + + sModeTable * table = map->modeTables; + + // save the target resolution for future use + map->currentX = x; + map->currentY = y; + + unlockVbios(map); + + // Get the aspect ratio for the requested mode + getAspectRatio(&map->aspectRatio, x, y); + + i = 0; + + // Call the vendor specific function for each available VESA Table + table = map->modeTables; + while (table != NULL) + { + //reset resolution value before treating a new table + x = map->currentX; + y = map->currentY; + + PRINT("Patching Table #%d : \n", table->id); + + map->setMode(table, i, &x, &y); +#ifdef AUTORES_DEBUG + getc(); +#endif + + table = table->next; + } + + relockVbios(map); + return; +} \ No newline at end of file Index: branches/azimutz/Chazi/i386/libsaio/autoresolution.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/autoresolution.h (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/autoresolution.h (revision 465) @@ -0,0 +1,145 @@ + +/* Copied from 915 resolution created by steve tomljenovic + * + * This code is based on the techniques used in : + * + * - 855patch. Many thanks to Christian Zietz (czietz gmx net) + * for demonstrating how to shadow the VBIOS into system RAM + * and then modify it. + * + * - 1280patch by Andrew Tipton (andrewtipton null li). + * + * - 855resolution by Alain Poirier + * + * This source code is into the public domain. + */ +#ifndef __915_RESOLUTION_H +#define __915_RESOLUTION_H + +#include "edid.h" + +#if DEBUG +#ifndef AUTORES_DEBUG +#define AUTORES_DEBUG +#endif +#endif + +#ifdef AUTORES_DEBUG +#define PRINT(a, b...) printf(a, ##b); +#else +#define PRINT(a, b...) verbose(a, ##b); +#endif + +#define __packed __attribute__((packed)) + +#define NEW(a) ((a *)(malloc(sizeof(a)))) +#define FREE(a) (free(a)) + +#define VBIOS_START 0xc0000 +#define VBIOS_SIZE 0x10000 + +#define FALSE 0 +#define TRUE 1 + + +bool gAutoResolution; + + +typedef struct +{ + uint8_t width; + uint8_t height; +} sAspect; + + +typedef enum +{ + CT_UNKWN, CT_830, CT_845G, CT_855GM, CT_865G, + CT_915G, CT_915GM, CT_945G, CT_945GM, CT_945GME, CT_946GZ, + CT_955X, CT_G965, CT_Q965, CT_965GM, CT_975X, + CT_P35, CT_X48, CT_B43, CT_Q45, CT_P45, + CT_GM45, CT_G41, CT_G31, CT_G45, CT_500 +} chipsetType; + + +typedef enum +{ + BT_UNKWN, BT_1, BT_2, BT_3, BT_ATI_1, BT_ATI_2, BT_NVDA +} biosType; + +typedef struct +{ + uint32_t clock; + uint16_t x; + uint16_t hSyncStart; + uint16_t hSyncEnd; + uint16_t hTotal; + uint16_t y; + uint16_t vSyncStart; + uint16_t vSyncEnd; + uint16_t vTotal; +} generic_modeline; + +typedef struct sModeTable_ +{ + uint8_t * pointer; + + uint8_t id; + uint32_t size; + uint32_t modeCount; + + uint8_t * backup; + + struct sModeTable_ *prev; + struct sModeTable_ *next; +} sModeTable; + + + +typedef struct +{ + uint32_t chipsetId; + chipsetType chipset; + biosType bios; + + uint8_t* biosBackupPtr; + uint8_t* biosPtr; + + sModeTable *modeTables; + + uint32_t currentX, currentY; + uint8_t b1, b2; + + bool hasSwitched; + + bool (*setMode)(sModeTable *,uint8_t,uint32_t*,uint32_t*); + + sAspect aspectRatio; + + uint8_t unlocked; +} vBiosMap; + +vBiosMap *map; + +vBiosMap * openVbios(chipsetType type); +void closeVbios (vBiosMap* map); + +void unlockVbios(vBiosMap* map); +void relockVbios(vBiosMap* map); + +void saveVbios(vBiosMap* map); +void restoreVbios(vBiosMap* map); + +void saveTables(sModeTable * table); +void restoreTables(vBiosMap * map, sModeTable * table); + +void gtfTimings(uint32_t x, uint32_t y, uint32_t freq, + uint32_t *clock, + uint16_t *hSyncStart, uint16_t *hSyncEnd, uint16_t *hBlank, + uint16_t *vSyncStart, uint16_t *vSyncEnd, uint16_t *vBlank); + +sModeTable * intializeTables(vBiosMap * map, int tablesCount); + +void patchVbios(vBiosMap* map, uint32_t x, uint32_t y, uint32_t bp, uint32_t hTotal, uint32_t vTotal); + +#endif Index: branches/azimutz/Chazi/i386/libsaio/nvidia_resolution.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/nvidia_resolution.c (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/nvidia_resolution.c (revision 465) @@ -0,0 +1,219 @@ +/* + * nvidia_resolution.c + * + * + * Created by Le Bidou on 19/03/10. + * Copyright 2010 ---. All rights reserved. + * + */ + +#include "nvidia_resolution.h" + +vBiosMap * openNvidiaVbios(vBiosMap *map) +{ + unsigned short nvDataTableOffset = 0; + unsigned short nvModeline_2_Offset = 0; + unsigned short * nvDataTable = NULL; + nvVesaTable * stdVesa; + + // initialize the table chain with two elements + sModeTable * table = intializeTables(map, 2); + /* + * Locate the VESA Tables + */ + + int i = 0; + //First VESA Table + while (i < 0x300) //We don't need to look for the table in the whole bios, the 768 first bytes only + { + if ((map->biosPtr[i] == 0x44) + && (map->biosPtr[i+1] == 0x01) + && (map->biosPtr[i+2] == 0x04) + && (map->biosPtr[i+3] == 0x00)) { + nvDataTableOffset = (unsigned short) (map->biosPtr[i+4] | (map->biosPtr[i+5] << 8)); + break; + } + i++; + } + + nvDataTable = (unsigned short *) (map->biosPtr + (nvDataTableOffset + OFFSET_TO_VESA_TABLE_INDEX)); + stdVesa = (nvVesaTable *) (map->biosPtr + *nvDataTable); + table->pointer = (uint8_t *) stdVesa + sizeof(nvCommonTableHeader); + printf("First Standard VESA Table at offset 0x%x\n",(unsigned int) (table->pointer - map->biosPtr)); + + //Second VESA Table + while (i < VBIOS_SIZE) //We don't know how to locate it other way + { + if ((map->biosPtr[i] == 0x40) && (map->biosPtr[i+1] == 0x01) //this is the first 320x200 modeline. + && (map->biosPtr[i+2] == 0xC8) && (map->biosPtr[i+3] == 0x00) + && (map->biosPtr[i+4] == 0x28) + && (map->biosPtr[i+5] == 0x18) + && (map->biosPtr[i+6] == 0x08) + && (map->biosPtr[i+7] == 0x08)) + { + nvModeline_2_Offset = (unsigned short) i; + break; + } + i++; + } + + if (nvModeline_2_Offset == (VBIOS_SIZE-1) || nvModeline_2_Offset == 0) + { + //If no second vesa table is available, free the corresponding table in chain + free(table->next); + table->next = NULL; + PRINT("There is no Second Standard VESA Table to patch\n"); + } + else + { + table = table->next; + table->pointer = map->biosPtr + nvModeline_2_Offset; + PRINT("Second Standard VESA Table at offset 0x%x\n", (unsigned int)(table->pointer - map->biosPtr)); + } + + if (table->prev->pointer == NULL) + { + PRINT("Unable to locate the mode table.\n"); + PRINT("Please run the program 'dumpBios' as root and\n"); + PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n"); + + closeVbios(map); + return 0; + } + + // reset the table pointer to the first in chain + table = map->modeTables; + + /* + * for each table in chain, figure out how many modes are available + * and what is the size of the table + */ + while (table != NULL) + { + table->modeCount = 0; + PRINT("Table #%d has ", table->id); + + if (table->id == MAIN_VESA_TABLE) + { + table->modeCount = stdVesa->header.tableSize & 0xff; + if (table->modeCount == 0) table->modeCount = 16; + table->size = table->modeCount * sizeof(nvModeline); + } + + if (table->id == SECOND_VESA_TABLE) + { + nvModeline_2 * modePtr = (nvModeline_2 *)table->pointer; + while (1) + { + if (modePtr[table->modeCount].hActive > 2048) break; + table->modeCount++; + } + if (table->modeCount == 0) table->modeCount = 31; + table->size = table->modeCount * sizeof(nvModeline_2); + } + + PRINT("%d modes\n", table->modeCount); + table = table->next; + } + + map->setMode = nvidiaSetMode; + + saveTables(map->modeTables); + +#ifdef AUTORES_DEBUG + PRINT("Press Any Key...\n"); + getc(); +#endif + + return map; +} + +bool nvidiaSetMode(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y) +{ + //In First VESA table, only first mode in table is patched + if (table->id == MAIN_VESA_TABLE) + { + nvModeline * modeTiming = (nvModeline *)table->pointer; + + // patch only if mode differs and if the mode to patch isn't a console mode + if (((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive)) + && (modeTiming[idx].hActive > 100)) + { + + PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive); + + if (modeTiming[idx].hActive != *x) + { + modeTiming[idx].hActive = *x; + modeTiming[idx].hActiveMinusOne = *x - 1; + modeTiming[idx].hActiveMinusOne_ = *x - 1; + } + + modeTiming[idx].vActive = *y; + modeTiming[idx].vActiveMinusOne = *y - 1; + modeTiming[idx].vActiveMinusOne_ = *y - 1; + + PRINT("%dx%d (%d %d %d %d %d %d)\n", + modeTiming[idx].hActive, + modeTiming[idx].vActive, + modeTiming[idx].hSyncStart, + modeTiming[idx].hSyncEnd, + modeTiming[idx].hTotal, + modeTiming[idx].vSyncStart, + modeTiming[idx].vSyncEnd, + modeTiming[idx].vTotal); + } + + //Since we are only patching the first mode, this deprecated + *x = modeTiming[idx + 1].hActive; + *y = modeTiming[idx + 1].vActive; + } + + if (table->id == SECOND_VESA_TABLE) + { + nvModeline_2 * modeTiming = (nvModeline_2 *) table->pointer; + int h = *y; + int w = *x; + + while (idx < table->modeCount) + { + *y = *x * h / w; + //patch only different mode in table except console modes and 320 wide modes + if (((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive)) + && (modeTiming[idx].hActive > 400)) + { + + PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive); + + if (modeTiming[idx].hActive != *x) + modeTiming[idx].hActive = *x; + + modeTiming[idx].vActive = *y; + + PRINT("%dx%d (%d %d %d %d ", + modeTiming[idx].hActive, + modeTiming[idx].vActive, + modeTiming[idx].hActive + modeTiming[idx].hSyncOffset, + modeTiming[idx].hActive + modeTiming[idx].hSyncOffset + modeTiming[idx].hSyncWidth, + modeTiming[idx].hActive + modeTiming[idx].hBlank, + modeTiming[idx].vActive + modeTiming[idx].vBlank); + + if ((modeTiming[idx].flags & HSyncPolarityMask) == HSyncPolarityMask) + { PRINT("H- "); } + else + { PRINT("H+ "); } + + if ((modeTiming[idx].flags & VSyncPolarityMask) == VSyncPolarityMask) + { PRINT("V-)\n"); } + else + { PRINT("V+)\n"); } + } + //returns the next mode in table + *x = modeTiming[idx + 1].hActive; + *y = modeTiming[idx + 1].vActive; + + idx++; + } + } + return TRUE; +} \ No newline at end of file Index: branches/azimutz/Chazi/i386/libsaio/nvidia_resolution.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/nvidia_resolution.h (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/nvidia_resolution.h (revision 465) @@ -0,0 +1,78 @@ +/* + * nviviaresolution.h + * + * + * Created by Le Bidou on 19/03/10. + * Copyright 2010 ---. All rights reserved. + * + */ + +#ifndef _NVDA_RESOLUTION_HEADER_ +#define _NVDA_RESOLUTION_HEADER_ + +#include "libsaio.h" +#include "autoresolution.h" + +#define NVIDIA_SIGNATURE "NVIDIA Corp" + +#define OFFSET_TO_VESA_TABLE_INDEX 2 +#define MAIN_VESA_TABLE 0 +#define SECOND_VESA_TABLE 1 + +#define HSyncPolarityMask 0x4 +#define VSyncPolarityMask 0x2 +#define isGraphicsModeMask 0x1 + +typedef struct { + unsigned char tableMajor; //These names are probably wrong + unsigned char tableMinor; + unsigned char tableRev; + unsigned short tableSize; +}__packed nvCommonTableHeader; + +typedef struct { + unsigned short clock; + unsigned short hActive; + unsigned short hActiveMinusOne; + unsigned short reserved1; + unsigned short hActiveMinusOne_; + unsigned short hSyncStart; + unsigned short hSyncEnd; + unsigned short hTotal; + unsigned short vActive; + unsigned short vActiveMinusOne; + unsigned short reserved2; + unsigned short vActiveMinusOne_; + unsigned short vSyncStart; + unsigned short vSyncEnd; + unsigned short vTotal; + unsigned short reserved3; +}__packed nvModeline; + +typedef struct { + unsigned short hActive; + unsigned short vActive; + unsigned char hBlank; + unsigned char hSyncOffset; + unsigned char hSyncWidth; + unsigned char vBlank; + //unsigned char vSyncwidth; + unsigned char flags; //looks like flags & 1 means "Graphics Mode", to oppose to "Console Mode" + //on 7xxx the high four bits look like a mode id number. + //on 8xxx only the low four bits are used, standard graphics mode are always 5. + // it can be 1 (1400x1050 and 2048x1536) (HSync High, VSync High ?) + // 3 (1440x900, 1680x1050 and 1920x1200) (HSync High, VSync Low ?) + // 5 (Standard Timings) (HSync Low, VSync High ?) + // or 7 (1280x800 and 768x340) (HSync Low, VSync Low ?) +}__packed nvModeline_2; + +typedef struct { + nvCommonTableHeader header; + nvModeline * modelines; +}__packed nvVesaTable; + +vBiosMap * openNvidiaVbios(vBiosMap *map); + +bool nvidiaSetMode(sModeTable* table, uint8_t idx, uint32_t* x, uint32_t* y); + +#endif \ No newline at end of file Index: branches/azimutz/Chazi/i386/libsaio/edid.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/edid.c (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/edid.c (revision 465) @@ -0,0 +1,145 @@ +/* + * edid.c + * + * + * Created by Evan Lojewski on 12/1/09. + * Copyright 2009. All rights reserved. + * + */ + + +#include "libsaio.h" +#include "edid.h" +#include "vbe.h" +#include "bootstruct.h" +#include "graphics.h" +#include "boot.h" + + +//static biosBuf_t bb; + +UInt32 xResolution = 0; +UInt32 yResolution = 0; +UInt32 bpResolution = 0; + + +void getResolution(UInt32* params) +{ + unsigned char* edidInfo = readEDID(); + + if(!edidInfo) { + xResolution = 1024; + yResolution = 768; + bpResolution = 32; + + free( edidInfo ); + } else { + // TODO: check *all* resolutions reported and eithe ruse the highest, or the native resolution (if there is a flag for that) + xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4); + yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4); + + bpResolution = 32; // assume 32bits + + free( edidInfo ); + + // Mode Sanity check + if ((xResolution < 1024) || !yResolution || !xResolution) + { + xResolution = 1024; + yResolution = 768; + } + + params[0] = xResolution; + params[1] = yResolution; + params[2] = bpResolution; + } +} + + +unsigned char* readEDID() +{ + SInt16 last_reported = -1; + UInt8 edidInfo[EDID_BLOCK_SIZE]; + + //UInt8 pointer; + + UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + int status; + unsigned int blocks_left = 1; + + do + { + // TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block + + bzero( edidInfo, EDID_BLOCK_SIZE); + + status = getEDID(edidInfo, blocks_left); + + //printf("Buffer location: 0x%X\n", SEG(buffer) << 16 | OFF(buffer)); + + /* + int j, i; + for (j = 0; j < 8; j++) { + for(i = 0; i < 16; i++) printf("0x%X ", ebiosInfo[((i+1) * (j + 1)) - 1]); + + } + printf("\n"); + */ + + if(status == 0) + { + //if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF) + if((memcmp(edidInfo, header1, sizeof(header1)) != 0) || + (memcmp(edidInfo, header2, sizeof(header2)) != 0) ) + { + blocks_left--; + int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ]; + + if ( reported > blocks_left ) + { + + printf("EDID claims %d more blocks left\n", reported); + } + + if ( (last_reported <= reported && last_reported != -1) + || reported == 0xff + /* 0xff frequently comes up in corrupt edids */ + //|| reported == MAGIC + ) + { + printf("Last reported %d\n", last_reported); + printf( "EDID blocks left is wrong.\n" + "Your EDID is probably invalid.\n"); + return 0; + } + else + { + //printf("Reading EDID block\n"); + //printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) ); + //printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) ); + + last_reported = reported; + blocks_left = reported; + } + } + else + { + printf("Invalid block %d\n", blocks_left); + printf("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) ); + printf("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) ); + return 0; + } + } else { + return 0; + } + + + blocks_left = 0; + } while(blocks_left); + + UInt8* ret = malloc(sizeof(edidInfo)); + memcpy(ret, edidInfo, sizeof(edidInfo)); + return (ret); +} Index: branches/azimutz/Chazi/i386/libsaio/edid.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/edid.h (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/edid.h (revision 465) @@ -0,0 +1,38 @@ +/* + * edid.h + * + * + * Created by Evan Lojewski on 12/1/09. + * Copyright 2009. All rights reserved. + * + */ + +#ifndef _EDID_H +#define _EDID_H + +#define EDID_BLOCK_SIZE 128 +#define EDID_V1_BLOCKS_TO_GO_OFFSET 126 + +#define SERVICE_REPORT_DDC 0 +#define SERVICE_READ_EDID 1 +#define SERVICE_LAST 1 // Read VDIF has been removed from the spec. + +#define FUNC_GET_EDID 0x4F15 + +typedef struct _edid_mode { + unsigned short pixel_clock; + unsigned short h_active; + unsigned short h_blanking; + unsigned short v_active; + unsigned short v_blanking; + unsigned short h_sync_offset; + unsigned short h_sync_width; + unsigned short v_sync_offset; + unsigned short v_sync_width; +}edid_mode; + + +unsigned char* readEDID(); +void getResolution(UInt32* params); + +#endif \ No newline at end of file Index: branches/azimutz/Chazi/i386/libsaio/gma_resolution.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/gma_resolution.c (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/gma_resolution.c (revision 465) @@ -0,0 +1,280 @@ +/* + * gmaResolution.c + * + * + * Created by Le Bidou on 19/03/10. + * Copyright 2010 ---. All rights reserved. + * + */ + +#include "gma_resolution.h" + +char * biosTypeNames[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"}; +int freqs[] = { 60, 75, 85 }; + + +vbiosResolutionType1 * mapType1Resolution(vBiosMap * map, uint16_t res) +{ + vbiosResolutionType1 * ptr = ((vbiosResolutionType1*)(map->biosPtr + res)); + return ptr; +} + +vbiosResolutionType2 * mapType2Resolution(vBiosMap * map, uint16_t res) +{ + vbiosResolutionType2 * ptr = ((vbiosResolutionType2*)(map->biosPtr + res)); + return ptr; +} + +vbiosResolutionType3 * mapType3Resolution(vBiosMap * map, uint16_t res) +{ + vbiosResolutionType3 * ptr = ((vbiosResolutionType3*)(map->biosPtr + res)); + return ptr; +} + +char detectBiosType(vBiosMap * map, char modeline, int entrySize) +{ + uint32_t i; + uint16_t r1, r2; + + vbiosMode * modeTable = (vbiosMode *)map->modeTables->pointer; + + r1 = r2 = 32000; + + for (i=0; i < map->modeTables->size; i++) + { + if (modeTable[i].resolution <= r1) + r1 = modeTable[i].resolution; + else if (modeTable[i].resolution <= r2) + r2 = modeTable[i].resolution; + } + + return (r2-r1-6) % entrySize == 0; +} + +vBiosMap * openIntelVbios(vBiosMap *map) +{ + /* + * Find the location of the Mode Table + */ + unsigned char* p = map->biosPtr + 16; + unsigned char* limit = map->biosPtr + VBIOS_SIZE - (3 * sizeof(vbiosMode)); + + // initialize the table chain with one element + sModeTable * table = intializeTables(map, 1); + + while (p < limit && table->pointer == 0) + { + vbiosMode* modePtr = (vbiosMode*) p; + + if (((modePtr[0].mode & 0xf0) == 0x30) && ((modePtr[1].mode & 0xf0) == 0x30) && + ((modePtr[2].mode & 0xf0) == 0x30) && ((modePtr[3].mode & 0xf0) == 0x30)) + { + + table->pointer = (uint8_t *)modePtr; + } + + p++; + } + + if (table->pointer == 0) + { + PRINT("Unable to locate the mode table.\n"); + PRINT("Please run the program 'dump_bios' as root and\n"); + PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n"); + + closeVbios(map); + return 0; + } + + PRINT("Mode Table at offset : 0x%x\n", (table->pointer) - map->biosPtr); + + /* + * Determine size of mode table + */ + + vbiosMode * modePtr = (vbiosMode *)table->pointer; + + while (modePtr->mode != 0xff) + { + table->size++; + modePtr++; + } + + table->modeCount = table->size; + PRINT("Mode Table size : %d\n", table->modeCount); + + /* + * Figure out what type of bios we have + * order of detection is important + */ + + if (detectBiosType(map, TRUE, sizeof(vbiosModelineType3))) + { + map->bios = BT_3; + map->setMode = intelSetMode_3; + PRINT("Bios Type : BT_3\n"); + } + else if (detectBiosType(map, TRUE, sizeof(vbiosModelineType2))) + { + map->bios = BT_2; + map->setMode = intelSetMode_2; + PRINT("Bios Type : BT_2\n"); + } + else if (detectBiosType(map, FALSE, sizeof(vbiosResolutionType1))) + { + map->bios = BT_1; + map->setMode = intelSetMode_1; + PRINT("Bios Type : BT_1\n"); + } + else + { + PRINT("Unable to determine bios type.\n"); + PRINT("Please run the program 'dump_bios' as root and\n"); + PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n"); + + return 0; + } + + return map; +} + + + +bool intelSetMode_1(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y) +{ + vbiosMode *modeTiming = (vbiosMode *) table->pointer; + vbiosResolutionType1 * res = mapType1Resolution(map, modeTiming[idx].resolution); + + //retreive the original mode's dimensions + uint32_t actualX = ((res->hActive2 & 0xf0) << 4) | (res->hActive1 & 0xff); + uint32_t actualY = ((res->vActive2 & 0xf0) << 4) | (res->vActive1 & 0xff); + + // patch only if mode differs + if ((*x != actualX) || (*y != actualY)) + { + PRINT("Mode %dx%d -> ", actualX, actualY); + + res->hActive2 = (res->hActive2 & 0x0f) | ((*x >> 4) & 0xf0); + res->hActive1 = (*x & 0xff); + + res->vActive2 = (res->hActive2 & 0x0f) | ((*y >> 4) & 0xf0); + res->vActive1 = (*y & 0xff); + + uint32_t actualX = ((res->hActive2 & 0xf0) << 4) | (res->hActive1 & 0xff); + uint32_t actualY = ((res->vActive2 & 0xf0) << 4) | (res->vActive1 & 0xff); + + PRINT("%dx%d \n", actualX, actualY); + } + + //since only the first mode is patched, this is deprecated + res = mapType1Resolution(map, modeTiming[idx + 1].resolution); + + actualX = ((res->hActive2 & 0xf0) << 4) | (res->hActive1 & 0xff); + actualY = ((res->vActive2 & 0xf0) << 4) | (res->vActive1 & 0xff); + + *x = actualX; + *y = actualY; + + return true; +} + +bool intelSetMode_2(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y) +{ + uint32_t xprev, yprev, j = 0; + + vbiosMode *modeTiming = (vbiosMode *) table->pointer; + vbiosResolutionType2 * res = mapType2Resolution(map, modeTiming[idx].resolution); + + //patch only if mode differs + if ( (*x != (res->modelines[0].hActive1 + 1)) + || (*y != (res->modelines[0].vActive1 + 1)) ) + { + + PRINT("Mode %dx%d -> ", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1); + + res->xChars = *x / 8; + res->yChars = *y / 16 - 1; + xprev = res->modelines[0].hActive1; + yprev = res->modelines[0].vActive1; + + // recalculate timigs for all frequencies and patch + for(j = 0; j < 3; j++) + { + vbiosModelineType2 * mode = &res->modelines[j]; + + if (mode->hActive1 == xprev && mode->vActive1 == yprev) + { + mode->hActive1 = mode->hActive2 = *x - 1; + mode->vActive1 = mode->vActive2 = *y - 1; + + gtfTimings(*x, *y, freqs[j], &mode->clock, + &mode->hSyncStart, &mode->hSyncEnd, + &mode->hBlank, &mode->vSyncStart, + &mode->vSyncEnd, &mode->vBlank); + + mode->hTotal = mode->hBlank; + mode->vTotal = mode->vBlank; + } + } + PRINT("%dx%d\n", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1); + + } + //since only the first mode is patched, this is deprecated + res = mapType2Resolution(map, modeTiming[idx + 1].resolution); + + *x = res->modelines[0].hActive1 + 1; + *y = res->modelines[0].vActive1 + 1; + + return true; +} + +bool intelSetMode_3(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y) +{ + uint32_t xprev, yprev, j = 0; + + vbiosMode *modeTiming = (vbiosMode *) table->pointer; + vbiosResolutionType3 * res = mapType3Resolution(map, modeTiming[idx].resolution); + + // patch only if mode differs + if ( (*x != (res->modelines[0].hActive1 + 1)) + || (*y != (res->modelines[0].vActive1 + 1)) ) + { + + PRINT("Mode %dx%d -> ", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1); + + xprev = res->modelines[0].hActive1; + yprev = res->modelines[0].vActive1; + + // recalculate timings for all frequencies and patch + for(j = 0; j < 3; j++) { + vbiosModelineType3 * mode = &res->modelines[j]; + + if (mode->hActive1 == xprev && mode->vActive1 == yprev) + { + mode->hActive1 = mode->hActive2 = *x - 1; + mode->vActive1 = mode->vActive2 = *y - 1; + + gtfTimings(*x, *y, freqs[j], &mode->clock, + &mode->hSyncStart, &mode->hSyncEnd, + &mode->hBlank, &mode->vSyncStart, + &mode->vSyncEnd, &mode->vBlank); + + mode->hTotal = mode->hBlank; + mode->vTotal = mode->vBlank; + + mode->timingH = *y-1; + mode->timingV = *x-1; + } + } + + PRINT("%dx%d\n", res->modelines[0].hActive1 + 1, res->modelines[0].vActive1 + 1); + + } + //since only the first mode is patched, this is deprecated + res = mapType3Resolution(map, modeTiming[idx + 1].resolution); + + *x = res->modelines[0].hActive1 + 1; + *y = res->modelines[0].vActive1 + 1; + + return true; +} \ No newline at end of file Index: branches/azimutz/Chazi/i386/libsaio/gma_resolution.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/gma_resolution.h (revision 0) +++ branches/azimutz/Chazi/i386/libsaio/gma_resolution.h (revision 465) @@ -0,0 +1,103 @@ +/* + * gma_resolution.h + * + * + * Created by Le Bidou on 19/03/10. + * Copyright 2010 ---. All rights reserved. + * + */ + +#ifndef _GMA_RESOLUTION_H_ +#define _GMA_RESOLTUION_H_ + +#include "libsaio.h" +#include "autoresolution.h" + +#define MODE_TABLE_OFFSET_845G 617 +#define INTEL_SIGNATURE "Intel Corp" + +typedef struct { + uint8_t mode; + uint8_t bitsPerPixel; + uint16_t resolution; + uint8_t unknown; +} __packed vbiosMode; + +typedef struct { + uint8_t unknow1[2]; + uint8_t hActive1; + uint8_t xTotal; + uint8_t hActive2; + uint8_t vActive1; + uint8_t yTotal; + uint8_t vActive2; +} __packed vbiosResolutionType1; + +typedef struct { + uint32_t clock; + + uint16_t hActive1; + uint16_t hTotal; + uint16_t hActive2; + uint16_t hBlank; + uint16_t hSyncStart; + uint16_t hSyncEnd; + uint16_t vActive1; + uint16_t vTotal; + uint16_t vActive2; + uint16_t vBlank; + uint16_t vSyncStart; + uint16_t vSyncEnd; +} __packed vbiosModelineType2; + +typedef struct { + uint8_t xChars; + uint8_t yChars; + uint8_t unknown[4]; + + vbiosModelineType2 modelines[]; +} __packed vbiosResolutionType2; + +typedef struct { + uint32_t clock; + + uint16_t hActive1; + uint16_t hTotal; + uint16_t hActive2; + uint16_t hBlank; + uint16_t hSyncStart; + uint16_t hSyncEnd; + + uint16_t vActive1; + uint16_t vTotal; + uint16_t vActive2; + uint16_t vBlank; + uint16_t vSyncStart; + uint16_t vSyncEnd; + + uint16_t timingH; + uint16_t timingV; + + uint8_t unknown[6]; +} __packed vbiosModelineType3; + +typedef struct { + unsigned char unknown[6]; + + vbiosModelineType3 modelines[]; +} __packed vbiosResolutionType3; + + +vbiosResolutionType1 * mapType1Resolution(vBiosMap * map, uint16_t res); +vbiosResolutionType2 * mapType2Resolution(vBiosMap * map, uint16_t res); +vbiosResolutionType3 * mapType3Resolution(vBiosMap * map, uint16_t res); + +char detectBiosType(vBiosMap * map, char modeline, int entrySize); + +vBiosMap * openIntelVbios(vBiosMap *); + +bool intelSetMode_1(sModeTable* table, uint8_t idx, uint32_t* x, uint32_t* y); +bool intelSetMode_2(sModeTable* table, uint8_t idx, uint32_t* x, uint32_t* y); +bool intelSetMode_3(sModeTable* table, uint8_t idx, uint32_t* x, uint32_t* y); + +#endif \ No newline at end of file