blob: f0c7bd6311f2a76dcd6cdd5eb461faee37f70113 [file] [log] [blame]
/****************************************************************************
*
* SciTech OS Portability Manager Library
*
* ========================================================================
*
* The contents of this file are subject to the SciTech MGL Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.scitechsoft.com/mgl-license.txt
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
*
* The Initial Developer of the Original Code is SciTech Software, Inc.
* All Rights Reserved.
*
* ========================================================================
*
* Language: ANSI C
* Environment: any
*
* Description: Simple test program to test the write combine functions.
*
* Note that this program should never be used in a production
* environment, because write combining needs to be handled
* with more intimate knowledge of the display hardware than
* you can obtain by simply examining the PCI configuration
* space.
*
****************************************************************************/
#include "pmapi.h"
#include "pcilib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/*------------------------- Global Variables ------------------------------*/
static int NumPCI = -1;
static PCIDeviceInfo *PCI;
static int *BridgeIndex;
static int *DeviceIndex;
static int NumBridges;
static PCIDeviceInfo *AGPBridge = NULL;
static int NumDevices;
/*-------------------------- Implementation -------------------------------*/
/****************************************************************************
RETURNS:
Number of display devices found.
REMARKS:
This function enumerates the number of available display devices on the
PCI bus, and returns the number found.
****************************************************************************/
static int PCI_enumerateDevices(void)
{
int i,j;
PCIDeviceInfo *info;
/* If this is the first time we have been called, enumerate all */
/* devices on the PCI bus. */
if (NumPCI == -1) {
if ((NumPCI = PCI_getNumDevices()) == 0)
return -1;
PCI = malloc(NumPCI * sizeof(PCI[0]));
BridgeIndex = malloc(NumPCI * sizeof(BridgeIndex[0]));
DeviceIndex = malloc(NumPCI * sizeof(DeviceIndex[0]));
if (!PCI || !BridgeIndex || !DeviceIndex)
return -1;
for (i = 0; i < NumPCI; i++)
PCI[i].dwSize = sizeof(PCI[i]);
if (PCI_enumerate(PCI) == 0)
return -1;
/* Build a list of all PCI bridge devices */
for (i = 0,NumBridges = 0,BridgeIndex[0] = -1; i < NumPCI; i++) {
if (PCI[i].BaseClass == PCI_BRIDGE_CLASS)
BridgeIndex[NumBridges++] = i;
}
/* Now build a list of all display class devices */
for (i = 0,NumDevices = 1,DeviceIndex[0] = -1; i < NumPCI; i++) {
if (PCI_IS_DISPLAY_CLASS(&PCI[i])) {
if ((PCI[i].Command & 0x3) == 0x3)
DeviceIndex[0] = i;
else
DeviceIndex[NumDevices++] = i;
if (PCI[i].slot.p.Bus != 0) {
/* This device is on a different bus than the primary */
/* PCI bus, so it is probably an AGP device. Find the */
/* AGP bus device that controls that bus so we can */
/* control it. */
for (j = 0; j < NumBridges; j++) {
info = (PCIDeviceInfo*)&PCI[BridgeIndex[j]];
if (info->u.type1.SecondayBusNumber == PCI[i].slot.p.Bus) {
AGPBridge = info;
break;
}
}
}
}
}
}
return NumDevices;
}
/****************************************************************************
REMARKS:
Enumerates useful information about attached display devices.
****************************************************************************/
static void ShowDisplayDevices(void)
{
int i,index;
printf("Displaying enumeration of %d PCI display devices\n", NumDevices);
printf("\n");
printf("DeviceID SubSystem Base10h (length ) Base14h (length )\n");
for (index = 0; index < NumDevices; index++) {
i = DeviceIndex[index];
printf("%04X:%04X %04X:%04X %08lX (%6ld KB) %08lX (%6ld KB)\n",
PCI[i].VendorID,
PCI[i].DeviceID,
PCI[i].u.type0.SubSystemVendorID,
PCI[i].u.type0.SubSystemID,
PCI[i].u.type0.BaseAddress10,
PCI[i].u.type0.BaseAddress10Len / 1024,
PCI[i].u.type0.BaseAddress14,
PCI[i].u.type0.BaseAddress14Len / 1024);
}
printf("\n");
}
/****************************************************************************
REMARKS:
Dumps the value for a write combine region to the display.
****************************************************************************/
static char *DecodeWCType(
uint type)
{
static char *names[] = {
"UNCACHABLE",
"WRCOMB",
"UNKNOWN",
"UNKNOWN",
"WRTHROUGH",
"WRPROT",
"WRBACK",
};
if (type <= PM_MTRR_MAX)
return names[type];
return "UNKNOWN";
}
/****************************************************************************
REMARKS:
Dumps the value for a write combine region to the display.
****************************************************************************/
static void PMAPI EnumWriteCombine(
ulong base,
ulong length,
uint type)
{
printf("%08lX %-10ld %s\n", base, length / 1024, DecodeWCType(type));
}
/****************************************************************************
PARAMETERS:
err - Error to log
REMARKS:
Function to log an error message if the MTRR write combining attempt failed.
****************************************************************************/
static void LogMTRRError(
int err)
{
if (err == PM_MTRR_ERR_OK)
return;
switch (err) {
case PM_MTRR_NOT_SUPPORTED:
printf("Failed: MTRR is not supported by host CPU\n");
break;
case PM_MTRR_ERR_PARAMS:
printf("Failed: Invalid parameters passed to PM_enableWriteCombined!\n");
break;
case PM_MTRR_ERR_NOT_4KB_ALIGNED:
printf("Failed: Address is not 4Kb aligned!\n");
break;
case PM_MTRR_ERR_BELOW_1MB:
printf("Failed: Addresses below 1Mb cannot be write combined!\n");
break;
case PM_MTRR_ERR_NOT_ALIGNED:
printf("Failed: Address is not correctly aligned for processor!\n");
break;
case PM_MTRR_ERR_OVERLAP:
printf("Failed: Address overlaps an existing region!\n");
break;
case PM_MTRR_ERR_TYPE_MISMATCH:
printf("Failed: Adress is contained with existing region, but type is different!\n");
break;
case PM_MTRR_ERR_NONE_FREE:
printf("Failed: Out of MTRR registers!\n");
break;
case PM_MTRR_ERR_NOWRCOMB:
printf("Failed: This processor does not support write combining!\n");
break;
case PM_MTRR_ERR_NO_OS_SUPPORT:
printf("Failed: MTRR is not supported by host OS\n");
break;
default:
printf("Failed: UNKNOWN ERROR!\n");
break;
}
exit(-1);
}
/****************************************************************************
REMARKS:
Shows all write combine regions.
****************************************************************************/
static void ShowWriteCombine(void)
{
printf("Base Length(KB) Type\n");
LogMTRRError(PM_enumWriteCombine(EnumWriteCombine));
printf("\n");
}
/****************************************************************************
REMARKS:
Dumps the value for a write combine region to the display.
****************************************************************************/
static void EnableWriteCombine(void)
{
int i,index;
for (index = 0; index < NumDevices; index++) {
i = DeviceIndex[index];
if (PCI[i].u.type0.BaseAddress10 & 0x8) {
LogMTRRError(PM_enableWriteCombine(
PCI[i].u.type0.BaseAddress10 & 0xFFFFFFF0,
PCI[i].u.type0.BaseAddress10Len,
PM_MTRR_WRCOMB));
}
if (PCI[i].u.type0.BaseAddress14 & 0x8) {
LogMTRRError(PM_enableWriteCombine(
PCI[i].u.type0.BaseAddress14 & 0xFFFFFFF0,
PCI[i].u.type0.BaseAddress14Len,
PM_MTRR_WRCOMB));
}
}
printf("\n");
ShowDisplayDevices();
ShowWriteCombine();
}
/****************************************************************************
REMARKS:
Dumps the value for a write combine region to the display.
****************************************************************************/
static void DisableWriteCombine(void)
{
int i,index;
for (index = 0; index < NumDevices; index++) {
i = DeviceIndex[index];
if (PCI[i].u.type0.BaseAddress10 & 0x8) {
LogMTRRError(PM_enableWriteCombine(
PCI[i].u.type0.BaseAddress10 & 0xFFFFFFF0,
PCI[i].u.type0.BaseAddress10Len,
PM_MTRR_UNCACHABLE));
}
if (PCI[i].u.type0.BaseAddress14 & 0x8) {
LogMTRRError(PM_enableWriteCombine(
PCI[i].u.type0.BaseAddress14 & 0xFFFFFFF0,
PCI[i].u.type0.BaseAddress14Len,
PM_MTRR_UNCACHABLE));
}
}
printf("\n");
ShowDisplayDevices();
ShowWriteCombine();
}
int main(int argc,char *argv[])
{
PM_init();
if (PCI_enumerateDevices() < 1) {
printf("No PCI display devices found!\n");
return -1;
}
if (argc < 2) {
printf("usage: uswc [-show -on -off]\n\n");
ShowDisplayDevices();
return -1;
}
if (stricmp(argv[1],"-show") == 0)
ShowWriteCombine();
else if (stricmp(argv[1],"-on") == 0)
EnableWriteCombine();
else if (stricmp(argv[1],"-off") == 0)
DisableWriteCombine();
return 0;
}