// Cyrix 6x86 Configuration under Windows NT, V 1.0 f. Visual C++ 2.0++
// c't 1/97, Matthias Witthopf, Andreas Stiller
// english Version
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include "directnt.h"
const char *DirectNTDrvName = "\\\\.\\Dev_DirectNT";
ULONG dummy;
BOOL DrvExec(HANDLE Drv,ULONG OpCode,ULONG Par1,ULONG Par2,ULONG Par3,
void *Result,ULONG ResultSize)
{
TDirectNTInfo I = {OpCode,Par1,Par2,Par3};
ULONG ResultLen;
if (DeviceIoControl(Drv,DWORD(IOCTL_DIRECTNT_CONTROL),&I,sizeof(I),
Result,ResultSize,&ResultLen,NULL))
return TRUE;
printf("Error in DirectNT.sys, Code = %d\n",GetLastError());
return FALSE;
}
HANDLE Drv;
BYTE getreg(ULONG index)
{
BYTE wert;
DrvExec(Drv,OP_WritePortByte,0x22,index,0,&wert,sizeof(wert));
DrvExec(Drv,OP_ReadPortByte,0x23,0,0,&wert,sizeof(wert));
return wert;
}
void setreg(ULONG index, BYTE wert)
{
DrvExec(Drv,OP_WritePortByte,0x22,index,0,&dummy,0);
DrvExec(Drv,OP_WritePortByte,0x23,wert,0,&dummy,0);
}
ULONG SearchFrameBuffer ()
{
ULONG indword;
for (ULONG i=0; i<0x20; i++) // searches on Bus 0, from Device 0 to Device 1Fh
{
DrvExec(Drv,OP_ReadPCIDword,8,i,0,&indword,sizeof(indword));
if (indword >> 24 == 3) break;
if (indword >> 16 == 1) break;
}
if (i>=0x20) return 0; // not found
DrvExec(Drv,OP_ReadPCIDword,0x10,i,0,&indword,sizeof(indword));
return indword & 0xFFFFFFFC;
}
void setARRx (BYTE nr, ULONG adr, BYTE size, BYTE attr)
{
BYTE ARRx=0xC4+3*nr;
BYTE RCRx=0xDC+nr;
setreg (ARRx, (BYTE)(adr >> 24));
setreg (ARRx+1, (BYTE)(adr >> 16 &0xFF));
setreg (ARRx+2, (BYTE)(adr >> 8 &0xF0) | size);
setreg (RCRx, attr);
}
ULONG getARRx (BYTE nr)
{
BYTE ARRx=0xC4+3*nr;
return ((ULONG)(getreg(ARRx)) << 24)
+((ULONG)(getreg(ARRx+1)) << 16)
+((ULONG)(getreg(ARRx+2)) << 8);
}
void setframe(BYTE attribut) // search framebuffer address in PCI configuration space
// search framebuffer in 6x86 ARR, if not found
// search unused 6x86 Address Range Register
{
ULONG framebuffer=SearchFrameBuffer();
if (!framebuffer)
{
printf ("Framebuffer not found\n");
return;
}
printf ("Framebuffer found at %08Xh\n",framebuffer);
BYTE CCR3= getreg (0xc3);
setreg (0xc3,(CCR3 & 0xF) | 0x10); // enable Mapping Register
// is framebuffer already in any ARRx ?
for (BYTE ARR=2; (ARR < 7) && ((getARRx(ARR) & 0xFFFFF000) != framebuffer);ARR++);
if (ARR==7) // no, not found
// then search unused ARR
for (BYTE ARR=2; (ARR < 7) && (getreg(0xC6+3*ARR) &0xF != 0);ARR++);
if (ARR==7)
printf ("No Address Region Register free");
else
{
setARRx (ARR,framebuffer,0xB,attribut); // Fixed Size of 16 MByte
printf ("New attribut %02Xh in Address Region Register %1X\n\n",attribut,ARR);
}
setreg (0xc3,CCR3); // restore old value CCR3
}
BOOL IsCyrix(void) // Uses differences of unused flags after division
{ // to distinguish between Cyrix and the rest
BYTE xah;
_asm {
xor ax,ax
sahf
mov ax,5
mov bx,2
div bl
lahf
mov xah,ah
}
return (xah==2);
}
int __cdecl main(int argc,char *argv[])
{
printf("Cyrix/IBM/ST 6x86 NT Configuration, ct 1/97 V1.0/Andreas Stiller \n");
Drv = CreateFile(DirectNTDrvName,GENERIC_READ,FILE_SHARE_READ,
NULL,OPEN_EXISTING,0,NULL);
if (Drv == INVALID_HANDLE_VALUE) {
printf("Error: Can't open DirectNT.sys!\n");
exit(1);
}
ULONG CR0;
BOOL waittast=FALSE;
if (!IsCyrix()) {
printf ("Cyrix/IBM/ST-Prozessor not detected");
exit (2);
}
BYTE DIR0=getreg(0xfe); // CPU Model & CORE/Clock-Ratio
BYTE DIR1=getreg(0xff); // Mask Step, 16h => 2.6, 17h => 2.7 ..
printf ("Cyrix/IBM/ST");
switch (DIR0 >> 4) {
case 0: printf(" 486SLC/DLC"); break;
case 1: printf(" 486S/DX/DX2");break;
case 2: printf(" 5x86");break;
case 3: printf(" 6x86");break;
case 4: printf(" M2"); break;
case 8: printf(" TI DX4"); break;
case 0xF:printf(" 486"); break;
default: printf(" Type unknown");
}
printf(",CPU-ID=%02Xh, mask revision= %02Xh\n",DIR0,DIR1);
BYTE CCR2=getreg(0xc2); // Read CCR2
BYTE CCR3=getreg(0xc3); // Read CCR3
BYTE CCR4=getreg(0xc4); // Read CCR4
BYTE CCR5=getreg(0xc5); // Read CCR5
if (!DrvExec(Drv,OP_GetCR0,0,0,0,&CR0,sizeof CR0))
printf("Can't read CR0\n");
printf("CCR2= %02Xh, CCR3= %02Xh, CCR4= %02Xh, CCR5= %02Xh, CR0=%08Xh\n\n",
CCR2,CCR3,CCR4,CCR5,CR0);
setreg(0xc2, CCR2 & ~4); // unlock of NW-Bit in CR0
for (int j=1; j<argc; j++) { // all the parameters
if (_stricmp(argv[j],"/WB")==0)
if (!DrvExec(Drv,OP_SetCR0,CR0 & ~(1 << 29),0,0,&dummy,0))
printf("Can't change CR0\n");
if (_stricmp(argv[j],"/WT")==0)
if (!DrvExec(Drv,OP_SetCR0,CR0 | (1 << 29),0,0,&dummy,0))
printf("Can't change CR0\n");
if (_stricmp(argv[j],"/SP")==0) // Suspend on Halt
CCR2 |=8;
if (_stricmp(argv[j],"/NSP")==0) // No Suspend on Halt
CCR2 &=~8;
if (_stricmp(argv[j],"/FF")==0) // Fast Framebuffer
setframe(0xb);
if (_stricmp(argv[j],"/NFF")==0) // Slow Framebuffer
setframe(0x1);
if (_stricmp(argv[j],"/ID")==0) // CPUID on
CCR4 |=0x80;
if (_stricmp(argv[j],"/NID")==0) // CPUID off
CCR4 &=~0x80;
if (_stricmp(argv[j],"/WA")==0) // WT_alloc on
CCR5 |=0x1;
if (_stricmp(argv[j],"/NWA")==0) // WT_alloc off
CCR5 &=~0x1;
if (_stricmp(argv[j],"/Wait")==0) // Console waits for key
waittast=TRUE;
}
setreg(0xc2,CCR2);
setreg(0xc3,CCR3);
setreg(0xc4,CCR4);
setreg(0xc5,CCR5);
printf("Suspend on Halt : ");
if (CCR2 & 8)
printf("on (Powersaving on)\n");
else
printf("off (Powersaving off)\n");
if (!DrvExec(Drv,OP_GetCR0,0,0,0,&CR0,sizeof CR0))
printf("Can't Read CR0\n");
printf("WB Mode L1-Cache: ");
if ((CR0 >> 29) & 1)
printf("off\n");
else
printf("on\n");
printf("CPUID : ");
if ((CCR4 >> 7) & 1)
printf("on\n");
else
printf("off\n");
printf("Write Allocation: ");
if (CCR5 & 1)
printf("fill on read/write miss\n");
else
printf("No fill on write miss\n");
printf("Lin Burst : ");
if ((CCR3 >> 7) & 1)
printf("on\n\n");
else
printf("off\n\n");
if (argc==1)
{
printf("Parameter: /WB :L1-Cache Write Back, /WT : L1-Cache Write Through \n");
printf(" /SP :Suspend on HALT activ,/NSP: passive\n");
printf(" /FF :Fast Framebuffer ,/NFF: Slow\n");
printf(" /ID :CPUID on ,/NID: CPUID off\n");
printf(" /WA :Write Allocation on ,/NWA: Write Allocation off\n");
printf(" /wait :Console waits for Key \n");
}
if (!CloseHandle(Drv))
printf("Error: Can't close DirectNT.sys!\n");
if (waittast) {
printf ("Go on with key");
dummy= getch();
}
return 0;
}