windows-nt/Source/XPSP1/NT/drivers/video/matrox/mga/mini/mtxpci.c
2020-09-26 16:20:57 +08:00

833 lines
29 KiB
C

/*****************************************************************************
* name: PCI acces module
*
* description: Acces the PCI functions in the BIOS
*
* designed: Christian Toutant, august 26, 1993
* last modified:
*
* version: $Id:
*
* function in modul:
*
******************************************************************************/
#include "switches.h"
#ifdef WINDOWS_NT
#include "dderror.h"
#include <string.h>
#endif /* #ifdef WINDOWS_NT */
#include "bind.h"
#include "defbind.h"
#include "def.h"
#include "mga.h"
#include "mgai_c.h"
#include "mgai.h"
#include "mtxpci.h"
/* GLOBAL */
word pciBoardInfo = 0;
/* Prototypes */
#ifdef WINDOWS_NT
//HACK!!!
typedef struct _MULTI_MODE
{
ULONG MulModeNumber; // unique mode Id
ULONG MulWidth; // total width of mode
ULONG MulHeight; // total height of mode
ULONG MulPixWidth; // pixel depth of mode
ULONG MulRefreshRate; // refresh rate of mode
USHORT MulArrayWidth; // number of boards arrayed along X
USHORT MulArrayHeight; // number of boards arrayed along Y
UCHAR MulBoardNb[NB_BOARD_MAX]; // board numbers of required boards
USHORT MulBoardMode[NB_BOARD_MAX]; // mode required from each board
HwModeData *MulHwModes[NB_BOARD_MAX]; // pointers to required HwModeData
} MULTI_MODE, *PMULTI_MODE;
/*--------------------------------------------------------------------------*\
| HW_DEVICE_EXTENSION
|
| Define device extension structure. This is device dependant/private
| information.
|
\*--------------------------------------------------------------------------*/
typedef struct _MGA_DEVICE_EXTENSION {
ULONG SuperModeNumber; // Current mode number
ULONG NumberOfSuperModes; // Total number of modes
PMULTI_MODE pSuperModes; // Array of super-modes structures
// For each board:
ULONG NumberOfModes[NB_BOARD_MAX]; // Number of available modes
ULONG NumberOfValidModes[NB_BOARD_MAX];
// Number of valid modes
ULONG ModeFlags2D[NB_BOARD_MAX]; // 2D modes supported by each board
ULONG ModeFlags3D[NB_BOARD_MAX]; // 3D modes supported by each board
USHORT ModeFreqs[NB_BOARD_MAX][64]; // Refresh rates bit fields
UCHAR ModeList[NB_BOARD_MAX][64]; // Valid hardware modes list
HwModeData *pMgaHwModes[NB_BOARD_MAX]; // Array of mode information structs.
BOOLEAN bUsingInt10; // May need this later
PVOID KernelModeMappedBaseAddress[NB_BOARD_MAX];
// Kern-mode virt addr base of MGA regs
PVOID UserModeMappedBaseAddress[NB_BOARD_MAX];
// User-mode virt addr base of MGA regs
PVOID MappedAddress[]; // NUM_MGA_COMMON_ACCESS_RANGES elements
} MGA_DEVICE_EXTENSION, *PMGA_DEVICE_EXTENSION;
void initConfigAddress( void );
int nextDevice( void );
dword getConfigData( int reg );
void setConfigData( int reg, dword donnee);
dword pciFindFirstMGA_1();
dword pciFindNextMGA_1();
void setAthenaRevision_1(void);
PUCHAR pciBiosCallAddr();
extern byte NbBoard;
extern HwData Hw[];
#endif /* #ifdef WINDOWS_NT */
bool pciBiosCall( union _REGS *r );
bool pciBiosPresent( PciBiosInfo *info);
dword pciFindFirstMGA();
dword pciFindNextMGA();
void setPciOptionReg();
void disPostedWFeature();
dword pciFindFirstMGA_2();
dword pciFindNextMGA_2();
#ifdef WINDOWS_NT
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,initConfigAddress)
#pragma alloc_text(PAGE,getConfigData)
#pragma alloc_text(PAGE,setConfigData)
#pragma alloc_text(PAGE,pciFindFirstMGA_1)
#pragma alloc_text(PAGE,pciFindNextMGA_1)
#pragma alloc_text(PAGE,pciBiosCall)
#pragma alloc_text(PAGE,pciBiosPresent)
#pragma alloc_text(PAGE,setAthenaRevision_1)
#pragma alloc_text(PAGE,pciFindFirstMGA)
#pragma alloc_text(PAGE,pciFindNextMGA)
#pragma alloc_text(PAGE,pciBiosCallAddr)
#pragma alloc_text(PAGE,setPciOptionReg)
#pragma alloc_text(PAGE,disPostedWFeature)
#pragma alloc_text(PAGE,pciFindFirstMGA_2)
#pragma alloc_text(PAGE,pciFindNextMGA_2)
#endif
#endif /* #ifdef WINDOWS_NT */
#if (!defined(WINDOWS_NT) || defined(MGA_WINNT31) || (!USE_VP_GET_ACCESS_RANGES))
/* The only part of this file required for Alpha under WinNT3.5 is setPciOptionReg */
word errorCode = 0;
static word
currentMgaIndexATL = 0;
currentMgaIndexATH = 0;
word configSpace = 0xffff;
/* Extern parameter */
extern dword MgaSel;
extern dword getmgasel(void);
#ifndef WINDOWS_NT
#else
extern PUCHAR pMgaBaseAddr;
extern PUCHAR setmgasel(dword MgaSel, dword phyadr, dword limit);
#endif
#ifdef WINDOWS_NT
#define SET_EAX(r,d) (r).e.reax = d
#define SET_EBX(r,d) (r).e.rebx = d
#define SET_ECX(r,d) (r).e.recx = d
#define SET_EDX(r,d) (r).e.redx = d
#define SET_AX(r,d) (r).x.ax = d
#define SET_BX(r,d) (r).x.bx = d
#define SET_CX(r,d) (r).x.cx = d
#define SET_DX(r,d) (r).x.dx = d
#define SET_SI(r,d) (r).x.si = d
#define SET_DI(r,d) (r).x.di = d
#define GET_EAX(r) ((r).e.reax)
#define GET_EBX(r) ((r).e.rebx)
#define GET_ECX(r) ((r).e.recx)
#define GET_EDX(r) ((r).e.redx)
#define GET_ESI(r) ((r).e.resi)
#define GET_EDI(r) ((r).e.redi)
#define GET_AX(r) ((r).x.ax)
#define GET_BX(r) ((r).x.bx)
#define GET_CX(r) ((r).x.cx)
#define GET_DX(r) ((r).x.dx)
#define GET_SI(r) ((r).x.si)
#define GET_DI(r) ((r).x.di)
VOID (*pciBiosRoutine)();
#define inp _inp
#define outp _outp
#define CONFIG_SPACE 0x0000c000
extern PUCHAR pMgaPciIo, pMgaPciConfigSpace;
extern PVOID pMgaDeviceExtension;
extern VIDEO_ACCESS_RANGE MgaPciConfigAccessRange, MgaPciCseAccessRange;
#define TITAN_PEL_ADDR_RD (PVOID) ((ULONG)(((PMGA_DEVICE_EXTENSION)pMgaDeviceExtension)->MappedAddress[3]) + (0x3c7 - 0x3c0))
#define TITAN_PEL_ADDR_WR (PVOID) ((ULONG)(((PMGA_DEVICE_EXTENSION)pMgaDeviceExtension)->MappedAddress[3]) + (0x3c8 - 0x3c0))
#define TITAN_PEL_DATA (PVOID) ((ULONG)(((PMGA_DEVICE_EXTENSION)pMgaDeviceExtension)->MappedAddress[3]) + (0x3c9 - 0x3c0))
// Mechanism 1 is used this way only for Windows NT.
/* Mechanism #1 interface */
#define CONFIG_ADDRESS 0xcf8
#define CONFIG_DATA 0xcfc
#define BUS_NUMBER_M 0x00ff0000h
#define DEV_NUMBER_M 0x0000f800h
#define BUS_NUMBER_A 16
#define DEV_NUMBER_A 11
#define REG_NUMBER_M 0xfc
#define MAGIG_ATLAS_NUMBER 0x0518102b
#define MAGIG_ATHENA_NUMBER 0x0D10102b
static dword currentBUS = 0;
static dword currentDEV = 0;
/*-------- Mechanism #1 */
void initConfigAddress()
{
dword adresse;
currentDEV = (dword)-1;
currentBUS = 0;
adresse = 0x80000000;
outdw(CONFIG_ADDRESS, adresse);
}
int nextDevice( void )
{
int trouve = 0;
dword magicID;
currentDEV++;
while ( !trouve && (currentBUS < 256) )
{
while ( !trouve && (currentDEV < 32 ) )
{
magicID = getConfigData( 0 );
trouve = ( magicID == MAGIG_ATLAS_NUMBER) ||
( magicID == MAGIG_ATHENA_NUMBER);
if (trouve)return -1;
currentDEV++;
}
currentDEV = 0;
currentBUS++;
}
return trouve;
}
dword getConfigData( int reg )
{
dword retVal, adresse;
adresse = 0x80000000 | (currentBUS << BUS_NUMBER_A)
| (currentDEV << DEV_NUMBER_A);
adresse |= reg & REG_NUMBER_M;
outdw(CONFIG_ADDRESS, adresse);
retVal = indw(CONFIG_DATA);
outdw(CONFIG_ADDRESS, 0);
return retVal;
}
void setConfigData( int reg, dword donnee)
{
dword adresse;
adresse = 0x80000000 | (currentBUS << BUS_NUMBER_A)
| (currentDEV << DEV_NUMBER_A);
adresse |= reg & REG_NUMBER_M;
outdw(CONFIG_ADDRESS, adresse);
outdw(CONFIG_DATA, donnee);
outdw(CONFIG_ADDRESS, 0);
}
/*----------------------------------------------------------------------------
| name: setAthenaRevision_1
|
| description: test acces to DAC in vgamode with snopping enabled
| if snooping not supporting, set pciBoardInfo to
| PCI_FLAG_ATHENA_REV1
|
| designed: Christian Toutant, octobre 14, 1994
| last modified:
|
|
| parameters: PciDevice *dev
| byte command
|
| modifies: pciBoardInfo
| calls: pciReadConfigByte, pciWriteConfigByte
| returns:
|
-----------------------------------------------------------------------------*/
void setAthenaRevision_1()
{
dword command;
dword classe;
dword baseAddress;
byte btmp;
command = getConfigData( 0x4 );
classe = getConfigData( 0x8 );
baseAddress = getConfigData( 0x10 );
if ( !(classe & 0x00800000) && !(command & (dword)3) )
{
command |= (dword)2;
setConfigData( 0x4, command);
if ((pMgaBaseAddr = setmgasel(MgaSel, baseAddress, 4)) != NULL)
{
mgaReadBYTE(*(pMgaBaseAddr+TITAN_OFFSET+TITAN_CONFIG+1),btmp);
mgaWriteBYTE(*(pMgaBaseAddr+TITAN_OFFSET+TITAN_CONFIG+1),btmp & ~(byte)4);
VideoPortFreeDeviceBase(pMgaDeviceExtension, pMgaBaseAddr);
}
}
if ( !(classe & 0x00800000) && !(command & (dword)PCI_SNOOPING) )
{
/* assume athena rev > 1 */
pciBoardInfo &= ~(word)PCI_FLAG_ATHENA_REV1;
/* init location 64 at 0 */
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64); /* reinit write addr */
/* empty fifo */
VideoPortReadPortUchar(TITAN_PEL_ADDR_RD);
/* active snooping */
setConfigData( 0x4, command | (dword)PCI_SNOOPING);
/* write to DAC in snooping mode */
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)0x11);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)0x22);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)0x33);
/* restore snooping */
setConfigData( 0x4, command );
/* now if the acces fail, we assume athena rev 1 */
VideoPortWritePortUchar(TITAN_PEL_ADDR_RD, (UCHAR)64); /* init read addr to loc 64 */
if (
(VideoPortReadPortUchar(TITAN_PEL_DATA) != 0x11) ||
(VideoPortReadPortUchar(TITAN_PEL_DATA) != 0x22) ||
(VideoPortReadPortUchar(TITAN_PEL_DATA) != 0x33)
) pciBoardInfo |= PCI_FLAG_ATHENA_REV1;
/* init location 64 at 0 */
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64); /* reinit write addr */
}
}
/*----------------------------------------------------------------------------
| name: pciFindFirstMGA_1
|
| description: Find the first MGA device in the system and return the base
| address of the device in the system (a succesive call to the
| function pciFindNextMGA give the address of other mga device
| in the system). Use harware mechanisme #1.
|
| designed: Christian Toutant, march 26, 1994
| last modified:
|
|
| parameters: none
| modifies: static variable currentIndex set to 1.
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: dword base address of the first mga found.
| -1 if no mga found (or no PCI BIOS found).
|
-----------------------------------------------------------------------------*/
dword pciFindFirstMGA_1()
{
initConfigAddress();
return pciFindNextMGA_1();
}
/*----------------------------------------------------------------------------
| name: pciFindNextMGA_1
|
| description: Find the next MGA device in the system and return the base
| address of the device the function pciFindFirstMGA must me call
| before call to this function. Use harware mechanisme #1.
|
|
| designed: Christian Toutant, march 26, 1994
| last modified:
|
|
| parameters: none
| modifies: static variable currentIndex is incremented by 1.
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: dword base address of the first mga found.
| -1 if no mga found (or no PCI BIOS found).
|
-----------------------------------------------------------------------------*/
dword pciFindNextMGA_1()
{
dword address = 0;
if ( nextDevice() )
{
setAthenaRevision_1();
address = getConfigData( 0x10 );
}
else
address = (dword)-1;
return address;
}
#endif /* #ifdef WINDOWS_NT */
/*----------------------------------------------------------------------------
| name: pciBiosCall
|
| description: call PCI BIOS function. The parameters is passed by register.
| reel mode
| 16 bit protected mode: The call is make via int 1aH
|
|
| 32 protected mode: The protected mode PCI BIOS is accessed by
| calling through a protected mode entry point
| in the PCI BIOS. The entry point and information
| needed for building segment descriptors are provided
| by teh BIOS32 Service Directory.
| see PCI BIOS SPECIFICATION rev 2.0 section 3.3.
|
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: union _REGS *r_in register need for the PCI Bus Specific Operation
| (AH must forced PCI_FUNCTION_ID (B1h))
|
| modifies: *r_out is modified to reflect the register state after the BIOS Call.
| calls: int 1ah
|
| returns: bool
| mtxOK int 1ah succes
| mtxFAIL int 1ah failed (see register for more information)
|
| note1: This implementation is compiler dependant, a different way for
| genarate interrupt may be use.
|
| note2: For now, we use the reel mode int 1ah.
| The entry point and structure initialisation needed for use
| the BIOS32 Service Directory we be implemented with the function
| pciBiosPresent.
| ref. PCI BIOS SPECIFICATION rev 2.0 section 3.3.
-----------------------------------------------------------------------------*/
bool pciBiosCall( union _REGS *r )
{
#ifdef WINDOWS_NT
return mtxFAIL;
#endif /* #ifdef WINDOWS_NT */
}
/*----------------------------------------------------------------------------
| name: pciBiosPresent
|
| description: Check if the PCI BIOS is present in the system. This function
| must be call before any call to PCI BIOS function.
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: PciBiosInfo *info information about the bios
| modifies: *info updated to bios found information
| calls:
| returns: bool
| mtxOK PCI bios found
| mtxFAIL otherwise
|
| note: if the BIOS32 Service Directory is implemented, this function
| must find the entry point and initialise all structure needed
| for call to BIOS function.
| ref. PCI BIOS SPECIFICATION rev 2.0 section 3.3.
-----------------------------------------------------------------------------*/
bool pciBiosPresent( PciBiosInfo *info)
{
#ifdef WINDOWS_NT
// We're not using this for now.
return mtxFAIL;
#endif /* #ifdef WINDOWS_NT */
}
/*----------------------------------------------------------------------------
| name: pciFindFirstMGA
|
| description: Find the first MGA device in the system and return the base
| address of the device in the system (a succesive call to the
| function pciFindNextMGA give the address of other mga device
| in the system).
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: none
| modifies: global variable MgaSel and pMgaBaseAddress
| static variable currentIndex set to 1.
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: dword base address of the first mga found.
| -1 if no mga found (or no PCI BIOS found).
|
-----------------------------------------------------------------------------*/
dword pciFindFirstMGA()
{
#ifdef WINDOWS_NT
return (dword)-1;
#endif /* #ifdef WINDOWS_NT */
}
/*----------------------------------------------------------------------------
| name: pciFindNextMGA
|
| description: Find the next MGA device in the system and return the base
| address of the device the function pciFindFirstMGA must me call
| before call to this function. This function search a mga device
| a currentIndex and increment the current index by 1. A call to
| pciFindFirstMGA set the currentIndex to 1.
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: none
| modifies: global variable MgaSel and pMgaBaseAddress
| static variable currentIndex is incremented by 1.
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: dword base address of the first mga found.
| -1 if no mga found (or no PCI BIOS found).
|
-----------------------------------------------------------------------------*/
dword pciFindNextMGA()
{
#ifdef WINDOWS_NT
return (dword)-1;
#endif /* #ifdef WINDOWS_NT */
}
#ifdef WINDOWS_NT
PUCHAR pciBiosCallAddr()
{
return((PUCHAR)NULL);
}
#endif /* #ifdef WINDOWS_NT */
#endif /* #if (!defined(WINDOWS_NT) || defined(MGA_WINNT31) || (!USE_VP_GET_ACCESS_RANGES)) */
#if (USE_VP_GET_ACCESS_RANGES)
extern PVOID pMgaDeviceExtension;
extern ULONG PciSlot;
#endif
#if 0
/*----------------------------------------------------------------------------
| name: setPciOptionReg
|
| description: set the option register of all mga to 1
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: none
| modifies:
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: void
|
-----------------------------------------------------------------------------*/
void setPciOptionReg()
{
#if (USE_VP_GET_ACCESS_RANGES)
UCHAR ConfigBuf = 0x01;
ULONG ConfigOffset = 0x40;
ULONG ConfigLength = 0x01;
VideoPortSetBusData(pMgaDeviceExtension, //PVOID HwDeviceExtension,
PCIConfiguration, //IN BUS_DATA_TYPE BusDataType,
PciSlot, //IN ULONG SlotNumber,
&ConfigBuf, //IN PVOID Buffer,
ConfigOffset, //IN ULONG Offset,
ConfigLength); //IN ULONG Length
#else /* #if (USE_VP_GET_ACCESS_RANGES) */
byte i;
// Use mechanism #1 also!!!
// Get access to ports before trying to map I/O configuration space.
if ((pMgaPciIo = VideoPortGetDeviceBase(pMgaDeviceExtension,
MgaPciCseAccessRange.RangeStart,
MgaPciCseAccessRange.RangeLength,
MgaPciCseAccessRange.RangeInIoSpace)) != NULL)
{
// Map I/O Configuration Space.
outp(pMgaPciIo+PCI_CSE-PCI_CSE, 0x80);
outp(pMgaPciIo+PCI_FORWARD-PCI_CSE, 0x00);
for (i = 0; i < NbBoard; i++)
{
if (Hw[i].ConfigSpace != 0)
{
MgaPciConfigAccessRange.RangeStart.LowPart = (ULONG)Hw[i].ConfigSpace;
if ((pMgaPciConfigSpace = VideoPortGetDeviceBase(pMgaDeviceExtension,
MgaPciConfigAccessRange.RangeStart,
MgaPciConfigAccessRange.RangeLength,
MgaPciConfigAccessRange.RangeInIoSpace)) != NULL)
{
outp(pMgaPciConfigSpace + 0x40, 0x01);
VideoPortFreeDeviceBase(pMgaDeviceExtension,pMgaPciConfigSpace);
}
}
outp(pMgaPciIo+PCI_CSE-PCI_CSE, 0x00);
VideoPortFreeDeviceBase(pMgaDeviceExtension,pMgaPciIo);
}
#endif /* #if (USE_VP_GET_ACCESS_RANGES) */
}
#endif //#if 0
#if (!defined(WINDOWS_NT) || defined(MGA_WINNT31) || (!USE_VP_GET_ACCESS_RANGES))
/*----------------------------------------------------------------------------
| name: pciFindFirstMGA_2
|
| description: Find the first MGA device in the system and return the base
| address of the device in the system (a succesive call to the
| function pciFindNextMGA give the address of other mga device
| in the system).
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: none
| modifies: global variable MgaSel and pMgaBaseAddress
| static variable currentIndex set to 1.
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: dword base address of the first mga found.
| -1 if no mga found (or no PCI BIOS found).
|
-----------------------------------------------------------------------------*/
dword pciFindFirstMGA_2()
{
dword address;
configSpace = 0x0000;
address = pciFindFirstMGA_1();
if (address == (dword)-1 )
{
configSpace = 0xc000;
return pciFindNextMGA_2();
}
else
{
return address;
}
}
/*----------------------------------------------------------------------------
| name: pciFindNextMGA_2
|
| description: Find the next MGA device in the system and return the base
| address of the device the function pciFindFirstMGA must me call
| before call to this function. This function search a mga device
| a currentIndex and increment the current index by 1. A call to
| pciFindFirstMGA set the currentIndex to 1.
|
| designed: Christian Toutant, august 26, 1993
| last modified:
|
|
| parameters: none
| modifies: global variable MgaSel and pMgaBaseAddress
| static variable currentIndex is incremented by 1.
| calls: pciBiosPresent, pciFindDevice, pciReadConfigDWord
| returns: dword base address of the first mga found.
| -1 if no mga found (or no PCI BIOS found).
|
-----------------------------------------------------------------------------*/
dword pciFindNextMGA_2()
{
byte command, subClass;
dword address = 0;
/* Map I/O Configuration Space */
address = pciFindNextMGA_1();
if (address != (dword)-1 )
return address;
// Restore this before going on, or you'll be sorry!
address = 0;
outp(pMgaPciIo+PCI_CSE-PCI_CSE, 0x80);
while (!address)
{
if (configSpace > 0xcf00)
{
address = (dword)-1;
outp(pMgaPciIo+PCI_CSE-PCI_CSE, 0x00);
}
else
{
// Get access to the current I/O space.
MgaPciConfigAccessRange.RangeStart.LowPart = (ULONG)configSpace;
if (VideoPortVerifyAccessRanges(pMgaDeviceExtension,
1,
&MgaPciConfigAccessRange) == NO_ERROR &&
(pMgaPciConfigSpace = VideoPortGetDeviceBase(pMgaDeviceExtension,
MgaPciConfigAccessRange.RangeStart,
MgaPciConfigAccessRange.RangeLength,
MgaPciConfigAccessRange.RangeInIoSpace)) != NULL)
{
if ((
(inp(pMgaPciConfigSpace ) == 0x2b) &&
(inp(pMgaPciConfigSpace + 1) == 0x10) &&
(inp(pMgaPciConfigSpace + 2) == 0x18) &&
(inp(pMgaPciConfigSpace + 3) == 0x05)
) ||
(
(inp(pMgaPciConfigSpace ) == 0x2b) &&
(inp(pMgaPciConfigSpace + 1) == 0x10) &&
(inp(pMgaPciConfigSpace + 2) == 0x10) &&
(inp(pMgaPciConfigSpace + 3) == 0x0D)
)
)
{
address = (dword)inp(pMgaPciConfigSpace + 0x13) << 24;
address |= (dword)inp(pMgaPciConfigSpace + 0x12) << 16;
address |= (dword)inp(pMgaPciConfigSpace + 0x11) << 8;
address |= (dword)(inp(pMgaPciConfigSpace + 0x10) & 0x0c);
command = inp(pMgaPciConfigSpace + PCI_COMMAND);
subClass = inp(pMgaPciConfigSpace + PCI_CLASS_CODE + 1);
/*--- Detect ATHENA revision < 2
If MGA board is in VGA mode and the snooping test fail, set
ATHENA rev 1 flag
---*/
/* Test if we are in vga mode & snooping disabled*/
if ( !subClass && !(command & PCI_SNOOPING) )
{
/* assume athena rev > 1 */
pciBoardInfo &= ~(word)PCI_FLAG_ATHENA_REV1;
/* init location 64 at 0 */
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64);
/* empty fifo */
VideoPortReadPortUchar(TITAN_PEL_ADDR_RD);
/* active snooping */
outp(pMgaPciConfigSpace + PCI_COMMAND,
(byte)(command | PCI_SNOOPING));
/* write to DAC in snooping mode */
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)0x11);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)0x22);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)0x33);
/* restore snooping */
outp(pMgaPciConfigSpace + PCI_COMMAND, (byte)command);
/* now if the acces fail, we assume athena rev 1 */
VideoPortWritePortUchar(TITAN_PEL_ADDR_RD, (UCHAR)64);
if (
(VideoPortReadPortUchar(TITAN_PEL_DATA) != 0x11) ||
(VideoPortReadPortUchar(TITAN_PEL_DATA) != 0x22) ||
(VideoPortReadPortUchar(TITAN_PEL_DATA) != 0x33)
) pciBoardInfo |= PCI_FLAG_ATHENA_REV1;
/* init location 64 at 0 */
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_DATA, (UCHAR)00);
VideoPortWritePortUchar(TITAN_PEL_ADDR_WR, (UCHAR)64); /* reinit write addr */
}
/*---- END Detect ATHENA revision < 2 */
/* If MGA board is in VGA mode and the MEM/IO space is not
enabled, enable it.
*/
if (!subClass && !(command & 0x03))
{
outp(pMgaPciConfigSpace + PCI_COMMAND,
(byte)(command | 2));
if ((pMgaBaseAddr = setmgasel(MgaSel, address, 4)) != NULL)
{
mgaReadBYTE(*(pMgaBaseAddr+TITAN_OFFSET+TITAN_CONFIG+1),
command);
mgaWriteBYTE(*(pMgaBaseAddr+TITAN_OFFSET+TITAN_CONFIG+1),
command & ~(byte)4);
VideoPortFreeDeviceBase(pMgaDeviceExtension,pMgaBaseAddr);
}
}
}
VideoPortFreeDeviceBase(pMgaDeviceExtension,pMgaPciConfigSpace);
}
}
configSpace += 0x100;
}
outp(pMgaPciIo+PCI_CSE-PCI_CSE, 0x00);
return address;
}
#endif /* #if (!defined(WINDOWS_NT) || defined(MGA_WINNT31) || (!USE_VP_GET_ACCESS_RANGES)) */