1 /****************************************************************************
3 * SciTech OS Portability Manager Library
5 * ========================================================================
7 * The contents of this file are subject to the SciTech MGL Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.scitechsoft.com/mgl-license.txt
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
27 * Description: Simple test program to test the write combine functions.
29 * Note that this program should never be used in a production
30 * environment, because write combining needs to be handled
31 * with more intimate knowledge of the display hardware than
32 * you can obtain by simply examining the PCI configuration
35 ****************************************************************************/
44 /*------------------------- Global Variables ------------------------------*/
46 static int NumPCI = -1;
47 static PCIDeviceInfo *PCI;
48 static int *BridgeIndex;
49 static int *DeviceIndex;
50 static int NumBridges;
51 static PCIDeviceInfo *AGPBridge = NULL;
52 static int NumDevices;
54 /*-------------------------- Implementation -------------------------------*/
56 /****************************************************************************
58 Number of display devices found.
61 This function enumerates the number of available display devices on the
62 PCI bus, and returns the number found.
63 ****************************************************************************/
64 static int PCI_enumerateDevices(void)
69 /* If this is the first time we have been called, enumerate all */
70 /* devices on the PCI bus. */
72 if ((NumPCI = PCI_getNumDevices()) == 0)
74 PCI = malloc(NumPCI * sizeof(PCI[0]));
75 BridgeIndex = malloc(NumPCI * sizeof(BridgeIndex[0]));
76 DeviceIndex = malloc(NumPCI * sizeof(DeviceIndex[0]));
77 if (!PCI || !BridgeIndex || !DeviceIndex)
79 for (i = 0; i < NumPCI; i++)
80 PCI[i].dwSize = sizeof(PCI[i]);
81 if (PCI_enumerate(PCI) == 0)
84 /* Build a list of all PCI bridge devices */
85 for (i = 0,NumBridges = 0,BridgeIndex[0] = -1; i < NumPCI; i++) {
86 if (PCI[i].BaseClass == PCI_BRIDGE_CLASS)
87 BridgeIndex[NumBridges++] = i;
90 /* Now build a list of all display class devices */
91 for (i = 0,NumDevices = 1,DeviceIndex[0] = -1; i < NumPCI; i++) {
92 if (PCI_IS_DISPLAY_CLASS(&PCI[i])) {
93 if ((PCI[i].Command & 0x3) == 0x3)
96 DeviceIndex[NumDevices++] = i;
97 if (PCI[i].slot.p.Bus != 0) {
98 /* This device is on a different bus than the primary */
99 /* PCI bus, so it is probably an AGP device. Find the */
100 /* AGP bus device that controls that bus so we can */
102 for (j = 0; j < NumBridges; j++) {
103 info = (PCIDeviceInfo*)&PCI[BridgeIndex[j]];
104 if (info->u.type1.SecondayBusNumber == PCI[i].slot.p.Bus) {
116 /****************************************************************************
118 Enumerates useful information about attached display devices.
119 ****************************************************************************/
120 static void ShowDisplayDevices(void)
124 printf("Displaying enumeration of %d PCI display devices\n", NumDevices);
126 printf("DeviceID SubSystem Base10h (length ) Base14h (length )\n");
127 for (index = 0; index < NumDevices; index++) {
128 i = DeviceIndex[index];
129 printf("%04X:%04X %04X:%04X %08lX (%6ld KB) %08lX (%6ld KB)\n",
132 PCI[i].u.type0.SubSystemVendorID,
133 PCI[i].u.type0.SubSystemID,
134 PCI[i].u.type0.BaseAddress10,
135 PCI[i].u.type0.BaseAddress10Len / 1024,
136 PCI[i].u.type0.BaseAddress14,
137 PCI[i].u.type0.BaseAddress14Len / 1024);
142 /****************************************************************************
144 Dumps the value for a write combine region to the display.
145 ****************************************************************************/
146 static char *DecodeWCType(
149 static char *names[] = {
158 if (type <= PM_MTRR_MAX)
163 /****************************************************************************
165 Dumps the value for a write combine region to the display.
166 ****************************************************************************/
167 static void PMAPI EnumWriteCombine(
172 printf("%08lX %-10ld %s\n", base, length / 1024, DecodeWCType(type));
175 /****************************************************************************
180 Function to log an error message if the MTRR write combining attempt failed.
181 ****************************************************************************/
182 static void LogMTRRError(
185 if (err == PM_MTRR_ERR_OK)
188 case PM_MTRR_NOT_SUPPORTED:
189 printf("Failed: MTRR is not supported by host CPU\n");
191 case PM_MTRR_ERR_PARAMS:
192 printf("Failed: Invalid parameters passed to PM_enableWriteCombined!\n");
194 case PM_MTRR_ERR_NOT_4KB_ALIGNED:
195 printf("Failed: Address is not 4Kb aligned!\n");
197 case PM_MTRR_ERR_BELOW_1MB:
198 printf("Failed: Addresses below 1Mb cannot be write combined!\n");
200 case PM_MTRR_ERR_NOT_ALIGNED:
201 printf("Failed: Address is not correctly aligned for processor!\n");
203 case PM_MTRR_ERR_OVERLAP:
204 printf("Failed: Address overlaps an existing region!\n");
206 case PM_MTRR_ERR_TYPE_MISMATCH:
207 printf("Failed: Adress is contained with existing region, but type is different!\n");
209 case PM_MTRR_ERR_NONE_FREE:
210 printf("Failed: Out of MTRR registers!\n");
212 case PM_MTRR_ERR_NOWRCOMB:
213 printf("Failed: This processor does not support write combining!\n");
215 case PM_MTRR_ERR_NO_OS_SUPPORT:
216 printf("Failed: MTRR is not supported by host OS\n");
219 printf("Failed: UNKNOWN ERROR!\n");
225 /****************************************************************************
227 Shows all write combine regions.
228 ****************************************************************************/
229 static void ShowWriteCombine(void)
231 printf("Base Length(KB) Type\n");
232 LogMTRRError(PM_enumWriteCombine(EnumWriteCombine));
236 /****************************************************************************
238 Dumps the value for a write combine region to the display.
239 ****************************************************************************/
240 static void EnableWriteCombine(void)
244 for (index = 0; index < NumDevices; index++) {
245 i = DeviceIndex[index];
246 if (PCI[i].u.type0.BaseAddress10 & 0x8) {
247 LogMTRRError(PM_enableWriteCombine(
248 PCI[i].u.type0.BaseAddress10 & 0xFFFFFFF0,
249 PCI[i].u.type0.BaseAddress10Len,
252 if (PCI[i].u.type0.BaseAddress14 & 0x8) {
253 LogMTRRError(PM_enableWriteCombine(
254 PCI[i].u.type0.BaseAddress14 & 0xFFFFFFF0,
255 PCI[i].u.type0.BaseAddress14Len,
260 ShowDisplayDevices();
264 /****************************************************************************
266 Dumps the value for a write combine region to the display.
267 ****************************************************************************/
268 static void DisableWriteCombine(void)
272 for (index = 0; index < NumDevices; index++) {
273 i = DeviceIndex[index];
274 if (PCI[i].u.type0.BaseAddress10 & 0x8) {
275 LogMTRRError(PM_enableWriteCombine(
276 PCI[i].u.type0.BaseAddress10 & 0xFFFFFFF0,
277 PCI[i].u.type0.BaseAddress10Len,
278 PM_MTRR_UNCACHABLE));
280 if (PCI[i].u.type0.BaseAddress14 & 0x8) {
281 LogMTRRError(PM_enableWriteCombine(
282 PCI[i].u.type0.BaseAddress14 & 0xFFFFFFF0,
283 PCI[i].u.type0.BaseAddress14Len,
284 PM_MTRR_UNCACHABLE));
288 ShowDisplayDevices();
292 int main(int argc,char *argv[])
295 if (PCI_enumerateDevices() < 1) {
296 printf("No PCI display devices found!\n");
300 printf("usage: uswc [-show -on -off]\n\n");
301 ShowDisplayDevices();
304 if (stricmp(argv[1],"-show") == 0)
306 else if (stricmp(argv[1],"-on") == 0)
307 EnableWriteCombine();
308 else if (stricmp(argv[1],"-off") == 0)
309 DisableWriteCombine();