VxD to allow Windows 3.1 Enhanced Mode to be used with Intel AHCI (SATA) controllers
This is a small and simple Virtual Device Driver ("VxD") for Windows 3.1 in 386 Enhanced Mode (and probably also Windows 95/98, though I haven't tested it with those!). Its purpose is to work around two bugs in the firmware for Intel AHCI controllers, which normally cause Windows 3.1 Enhanced Mode to crash on disk access.
The AHCI firmware contains code needed to service int 13h
calls from Real/Virtual 8086 Mode, which works pretty well for the most part. In Virtual 8086 Mode, it uses the Virtual DMA Specification to cooperate with the running Virtual Machine Manager (e.g. EMM386, or Windows 3.1) and ensure that data gets read into / written from the correct physical addresses. Unfortunately, there are two mistakes in its use of the Spec:
- When it locks a contiguous or scatter / gather region, it sets the
ES
register to the Extended BIOS Data Area (EBDA), but when doing the corresponding unlock(s), it instead usesDS
! This is wrong, and causes Windows 3.1 to crash because it's trying to read a DMA Descriptor Structure from arbitrary memory that wasn't used to set one up in the first place (but EMM386 is more resilient…). - This one's a bit more subtle, and it may be particular to my motherboard / system: the firmware sets up an Extended DMA Descriptor Structure at the beginning of the EBDA, instead of somewhere deep inside it. This means that, depending on how large the scatter / gather regions are, it can overwrite varying amounts of data that are supposed to be at the beginning of the EBDA. For example, I found that when I worked around Bug 1, Windows would boot, but the mouse didn't work anymore because the "pointing device" info was getting overwritten in the EBDA! The offset within the EBDA is supposed to be specified at a certain location in the firmware ROM, but for some reason it's set to zero (again, this may just be on my motherboard…).
To build the VxD, you need the Win16 Driver Development Kit. Once you install it, you can place the sources in a subfolder of the 386
directory (e.g. 386\AHCIFIX
) and run nmake
. This should create the file AHCIFIX.386
which can be loaded by Windows.
By the way, here's a tip for using the DDK on a modern system: to make the debugger WDEB386
work, you need to change some bytes:
- At position
63D8
, you need to change0F 24 F0
to66 33 C0
- At position
63DF
, you need to change0F 24 F8
to66 33 C0
This removes references to the TR6
and TR7
registers, which crash the system since they only existed on the 386, 486 and a few other less-well-known chips!
Simply add device=ahcifix.386
to the [386Enh]
section of C:\WINDOWS\SYSTEM.INI
. You should specify the full path, or else copy the file AHCIFIX.386
to C:\WINDOWS\SYSTEM
. You can get the file by building it as described above, or by downloading a release.
Alternatively (or additionally), if using a DOS Memory Manager, such as EMM386, you can add ahcifixd.sys
to your CONFIG.SYS
file, including the full path to ahcifix.386
after it on the same line. For example:
DEVICE=C:\AHCIFIXD\AHCIFIXD.SYS C:\WIN16DDK\386\AHCIFIX\AHCIFIX.386
NOTE: This driver works for me, on the one motherboard I have tested it on (this motherboard)! Please proceed with caution if trying it on a different motherboard!