📄 init.c
字号:
MEM_RELEASE);
// Reset the chip.
ResetChip();
// Now, we need to send the initialization table.
ProcessInitializationTable();
}
else {
Error(L"Unable to map physical address to virtual address!\n");
}
}
else {
Error(L"Unable to translate bus address to physical address!\n");
}
}
else {
Error(L"Unable to allocate virtual address for ROM!\n");
}
}
}
if (FnRetVal == FALSE) {
Message(L"Rom access is disabled. Generating initialization table.\n");
FnRetVal = GenerateRomTable();
}
Exit(L"InitializeRom");
return FnRetVal;
}
BOOL
CopyRomTable(
LPVOID RomImage
)
{
// CopyRomTable
// This function takes the address of the Permedia3 ROM. It reads the ROM and
// extracts the register initialization table into the g_Config global.
// Local variables.
BOOL FnRetVal = FALSE; // Return value for this function.
ULONG * Table;
USHORT TableOffset;
ULONG TableHeader;
ULONG TableBytes;
Enter(L"CopyRomTable");
g_Config.InitializationTableEntries = 0;
// Read the 2 byte BIOS version number.
g_Config.BiosVersionMajorNumber = *((BYTE *)RomImage + ROM_MAJOR_VER_OFFSET);
g_Config.BiosVersionMinorNumber = *((BYTE *)RomImage + ROM_MINOR_VER_OFFSET);
// There is double indirection to the ROM initialization table. We first look
// at a constant offset from ther beginning of ROM to get the offset of the
// table.
TableOffset = *(USHORT *)((BYTE *)RomImage + ROM_TABLE_OFFSET_OFFSET);
Table = (ULONG *)((BYTE *)RomImage + TableOffset);
// The table header (32 bits) has an identification code and a count
// of the number of entries in the table.
TableHeader = *Table++;
// The top two bytes of the parition header should be 3D Labs PCI Vendor Id.
while ((TableHeader >> 16) == VENDOR_ID) {
// The 2nd lowest byte is the BIOS partition type.
switch ((TableHeader >> 8) & 0xFF) {
case 0:
// BIOS partition 0. This BIOS region holds the memory timings for the
// Permedia3 chip.
// Get the number of register address & data pairs from the header. It's
// the low byte.
g_Config.InitializationTableEntries = TableHeader & 0x000000FF;
Assert(g_Config.InitializationTableEntries != 0);
// Allocate memory for the table. Note that each entry is 2 4 byte
// values, or the number of bytes in the table is 8 times the number
// of entries.
TableBytes = g_Config.InitializationTableEntries * 8;
g_Config.InitializationTable = (ULONG *)SystemAlloc(TableBytes);
if (g_Config.InitializationTable != NULL) {
// Copy the initilization sequence from ROM to system memory.
memcpy(g_Config.InitializationTable,
Table,
TableBytes);
FnRetVal = TRUE;
}
else {
Error(L"Unable to allocate system memory for register initialization table.\n");
}
break;
case 1:
// BIOS partition 1. This BIOS region holds extended clock settings for
// PXRX chips.
g_Config.HaveExtendedClocks = TRUE;
g_Config.PXRXCoreClock = ((*Table++) & 0x00FFFFFF) * 1000 * 1000;
g_Config.PXRXMemoryClock = *Table++;
g_Config.PXRXMemoryClockSrc = (g_Config.PXRXMemoryClock >> 28) << 4;
g_Config.PXRXMemoryClock = (g_Config.PXRXMemoryClock & 0x00FFFFFF) * 1000 * 1000;
g_Config.PXRXSetupClock = *Table++;
g_Config.PXRXSetupClockSrc = (g_Config.PXRXSetupClock >> 28) << 4;
g_Config.PXRXSetupClock = (g_Config.PXRXSetupClock & 0x00FFFFFF) * 1000 * 1000;
g_Config.PXRXGammaClock = ((*Table++) & 0x00FFFFFF) * 1000 * 1000;
g_Config.PXRXCoreClockAlt = ((*Table++) & 0x00FFFFFF) * 1000 * 1000;
break;
default:
Error(L"Found unknown BIOS ROM partition type.\n");
break;
}
// Get next partition header.
TableHeader = *Table++;
}
Exit(L"CopyRomTable");
return FnRetVal;
}
BOOL
GenerateRomTable()
{
// GenerateRomTable
// This function is called if access to the Permedia3 ROM BIOS table cannot
// be established. It atempts to load some sensible default values into
// the initialization table.
// Local constants.
const ULONG TableEntries = 4;
const ULONG TableBytes = sizeof(ULONG) * TableEntries * 2;
// Local variables.
BOOL FnRetVal = FALSE; // Return value for this function.
Enter(L"GenerateRomTable");
#ifdef CEPC
// No video BIOS information available...
g_Config.BiosVersionMajorNumber = 0;
g_Config.BiosVersionMinorNumber = 0;
// No extended settings are currently used...
g_Config.HaveExtendedClocks = FALSE;
g_Config.InitializationTableEntries = TableEntries;
g_Config.InitializationTable = (ULONG *)SystemAlloc(TableBytes);
if (g_Config.InitializationTable != NULL) {
// The system BIOS has already initialized the card, and we have yet to
// reset it, so we can read out the values we need for our initialization
// table to feed it back into the card after reset.
g_Config.InitializationTable[0] = r_LocalMemCaps;
g_Config.InitializationTable[1] = ReadRegUlong(r_LocalMemCaps);
g_Config.InitializationTable[2] = r_LocalMemControl;
g_Config.InitializationTable[3] = ReadRegUlong(r_LocalMemControl);
g_Config.InitializationTable[4] = r_LocalMemRefresh;
g_Config.InitializationTable[5] = ReadRegUlong(r_LocalMemRefresh);
g_Config.InitializationTable[6] = r_LocalMemTiming;
g_Config.InitializationTable[7] = ReadRegUlong(r_LocalMemTiming);
FnRetVal = TRUE;
}
else {
Error(L"Unable to allocate system memory for register initialization table.\n");
}
#else
Error(L"GenerateRomTable does not work on platforms with no system BIOS!\n");
#endif
Exit(L"GenerateRomTable");
return FnRetVal;
}
void
ResetChip()
{
// ResetChip
// This function sends a software reset to the chip, so that we can begin
// with a clean slate. Once the reset is sent, we poll the ResetStatus
// register to wait for it to finish. We also insure that the VGA is
// turned off.
Enter(L"ResetChip");
// Writing any value to ResetStatus should cause a reset.
WriteRegUlong(r_ResetStatus, 0);
// Wait for the reset to complete.
while (ReadMaskedRegUlong(r_ResetStatus, b_ResetStatus_SoftwareResetFlag) != 0);
// Now, make sure that P3 is not in VGA mode, start by unlocking the VGA.
// The values 0x3D and 0xDB are arbitrary and mandated by the Permedia3
// Reference Guide, pg. 4-122.
WriteVgaReg(r_VGALockExtended1Reg, 0x3D);
WriteVgaReg(r_VGALockExtended2Reg, 0xDB);
// Disable the VGA.
WriteMaskedVgaReg(r_VGAControlReg, b_VGAControlReg_EnableVGADisplay, 0);
// Finish by re-locking the extended VGA registers. We need only write
// anything but the magic combination.
WriteVgaReg(r_VGALockExtended1Reg, 0);
Exit(L"ResetChip");
}
void
ProcessInitializationTable()
{
// ProcessInitializationTable
// By the time that the InitializeRegister call is made, we should have
// already read or generated an initialization table. This function sends
// that table to the hardware.
// Local variables.
ULONG * Table = g_Config.InitializationTable;
ULONG TableEntries = g_Config.InitializationTableEntries;
ULONG Register;
ULONG Data;
Enter(L"ProcessInitializationTable");
WaitForInputFIFO(TableEntries);
while (TableEntries--) {
Register = *Table++;
Data = *Table++;
WriteRegUlong(Register, Data);
}
Exit(L"ProcessInitializationTable");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -