VIASBLat fixes a latency problem with the SBPCI 128 on my Via Apollo133 Pro motherboard (i.e. crackling noise, static, choppy sound in Windows 2000/XP when there's a lot of traffic on the PCI bus).
Please note that PCI slot and latency is hardcoded in this kernel driver, and for it to be of any use for you, you will need to edit the source code and recompile. Compilation requires MS VC++ 6.0 and a current version of the NT Device Driver Kit (and knowing how to use them).
The NTDDK for Windows 2000 was used (which is 66 MB), however it is no longer available for download on the Microsoft download site, neither is the Windows XP DDK, you may order it on CD though. Or, you may want to search for it on the net, the filename is win2kddk.exe (68905688 bytes, md5=287b12f965d8f0cf27c4430f1c84df22). Finally, ISO's or installer .exe's can be had from the p2p eDonkey/eMule network. The Windows 2000 DDK has been superseded by the XP(sp1) and 2003 Server DDK's.
Anyway, here you go: viasblat.zip.
Copy VIASBLat.SYS to
%windir%\System32\Drivers and add it as a kernel driver (incorporate viasblat.reg into
the registry, then reboot). Once it is recognized as a service, it can be
started/stopped with "net start viasblat" or "net stop
viasblat". For Windows XP, you may also use "sc start
viasblat" or "sc stop viasblat". You can query driver
status with "sc query viasblat". The driver should load on boot
when using the supplied .reg file.
As I said, the driver as it is when you download it, will probably not work on your system (may very well crash it, crashing auto-loading drivers are bad, mmkay?). The driver writes to some PCI configuration registers at each reboot/unsuspend.
VOID adjustLatency() {
ULONG cfb=_inp(0xCFB); // read pci mechanism control reg
// bus dev func dword addr
ULONG confaddr=(1<<31) | (0 << 16) | ((ULONG)11 << 11) | (0 << 8) | (0x0C);
_asm pushf
_asm cli
_outp (0xCFB, cfb | 1); // select mech #1 ???
_outp (0xCFA, 0); // bus #0 ???
_outpd (0xCF8, confaddr);
_outpd (0xCFC, 0x00004000); // 0x0d:40 : latency
_outp (0xCFB, cfb);
_asm popf
}
There are four thing to adjust here (adjust the numbers just before the
"<<")
Next, you can adjust the value that is written to the register. The easiest way to find out bus, dev, function, address and value would be to use WPCREDIT.
Note that the value is 32-bit, and all 4 bytes are written. The latency register is a byte at 0x0D, it is changed by writing a DWORD to 0x0C (!). Therefore, the final value that is written to 0x0D is the second byte of the DWORD value. You can adjust the DWORD value on the line:
_outpd (0xCFC, 0x00004000);
Here, 0x00004000 is written to address 0x0C, placing 0x40 at 0x0D, hereby modifying the PCI latency to 0x40.
If you need to modify single bytes, without clobbering the surrounding bytes (which conveniently were 0 here), you will need to read the DWORD first, change the byte value, then write the DWORD back. More information is provided in the viasblat.cpp source code, in the form of an excerpt from Ralf Brown's IO port list. You may want to add WPCRSET-like functionality, were bus, dev, func, address, value are read from the registry. I have no intention to add it myself though.
If you experience crashes or (worse) blue-screen on boot, and last-known-good fails:
Take care.
It is somewhat based on DirectNT. Correct latency settings were determined with WPCRSET & WPCREDIT. WPCRSET has similar functionality as VIASBLat, but it does not reapply PCI settings after awaking from hibernate (VIASBLat does!).
"PCI Latency patch" for VIA chipsets also has hibernate/stand-by support, but it is closed source and configuration is limited (and it didn't help for my problem).
VIASBLat is public domain.