A reader comment on a previous post on ISA DMA pointed out that UMBPCI (or rather the DMACHK utility distributed with it) does something unusual with regard to ISA DMA. There was a suspicion of somehow accomplishing the mythical memory-to-memory DMA transfers; that proved to be unfounded, at least in the UMBPCI case, but what the utility does is nevertheless quite interesting.
First some background about what DMACHK does and why it exists in the first place. UMBs are generally prone to causing difficulty with DMA, and UMBPCI is no exception. The way UMBPCI works is that it enables memory between 640KB to 1MB for use with UMBs. Such memory is normally only intended for ROM shadowing and in some chipsets, it is not accessible via DMA (whereas EMM386/QEMM/386MAX use paging to remap normal memory into the UMB range, causing physical addresses to differ from linear ones).
Because DMA may be necessary to effectively use UMBs (booting from floppy or a bus-mastering hard disk controller), it is rather useful to know whether DMA works in a given UMB range. But how does one test whether ISA DMA can access UMBs without requiring a DMA-capable device? The method DMACHK uses is quite ingenious.
To check a given UMB range for DMA accessibility, DMACHK performs roughly the following sequence of steps:
- Fill a 1KB buffer in the tested memory region with a 55AAh pattern
- Unmask DMA channel 1 and program it to target 1KB buffer
- Set DMA channel 1 for writing in block transfer mode
- Set the 8237’s DMA Request register bit for channel 1
- Read the DMA Status register in a loop which terminates when either the T/C bit for DMA channel 1 becomes set or a given timeout period elapses
- Check whether the 1KB range is still filled with the 55AAh pattern
- If it is not, DMA is working
How does this work and why? The block transfer mode is not normally used at all because it locks out any other bus accesses. However, it has the interesting property that it can be triggered by software (through the 8237’s Request register), which is probably related to the fact that block transfers are the only type that can be used for memory-to-memory DMA.
Now, in a typical PC, chances are there’s no device using DMA channel 1, or perhaps there might be a sound card using it. But DMACHK does not program any hardware beyond the 8237 DMA controller.
The catch is that if a block write DMA transfer is triggered by software, the 8237 will drive the bus, and something will get written to the memory. If no device provides data on the bus, most likely a sequence of 0FFh bytes will be written. It might be something else, but if DMA can target the memory, the memory will be written to.
That is exactly what DMACHK takes advantage of. It does not care what gets written to the memory, it only cares whether the 55AAh pattern changed. Now, since DMA channel 1 is 8-bit, the memory might theoretically get written with 55h bytes or with 0AAh bytes, but it is very difficult to imagine how it would be written with a sequence of alternating 0AAh and 55h bytes. Therefore if the 55AAh pattern remains undisturbed, it is safe to conclude that DMA is not working, but if the 55AAh patter is not intact, it must mean DMA works (or the RAM is bad, but then DMA is the least of one’s problems).
It has been experimentally confirmed that on at least one system (Alaris Cougar board, OPTi 82C499 chipset, 486 CPU), this kind of DMA transfer fills the buffer memory with 0FFh bytes. That is precisely the expected result on a typical system where reads from an “empty” data bus return with all bits set.
Not So Fast!
As mentioned in the previous post, a characteristic of 8237 DMA transfers is that when the DMA controller is accessing the bus, the CPU is locked out, together with any other possible bus agents. When DMA transfers are running, the CPU is slowed down because it has to share bandwidth with DMA transfers, or wait for their completion in the case of block DMA transfers.
This “bug” can be turned into a feature if the goal is to slow down the CPU. It was done at least twice with DMASLO (1988) and DMAKO (1992). Both utilities use the same principle described above: When DMA is running, the CPU isn’t, especially on older machines with no cache or less sophisticated cache controllers.
What the utilities do in detail is quite different, suggesting that they were developed entirely independently.
The DMASLO utility runs on XTs as well as ATs and was developed to allow old games to work on newer PCs, especially games with joystick support. These were often CPU speed dependent and failed on faster PCs. DMASLO can be tuned to slow down newer systems (“newer” as of the late 1980s) to perform like old XTs.
DMASLO can use any of the four channels on the first (and possibly only) DMA controller, with the obvious caveat that reprogramming DMA channel 0 on a PC/XT is likely fatal. DMASLO programs the channel for a verify transfer which is interesting because it goes through all the motions of a normal DMA transfer—xcept actually transferring any data. DMASLO also uses block transfers which entirely lock out any other bus access, and the length of the transfers can be set by the user. By default it’s one, and of course the DMA channel is set to auto-init. When the DMA transfer is (automatically) restarted, the CPU has a little bit of time to do something. Thanks to this, DMASLO is a very powerful handbrake and can slow down a system to a crawl.
DMASLO uses an interesting method of triggering DMA transfers. It changes the DREQ polarity in the 8237, which means that a previously inactive DREQ signal will instantly turn into an active one.
DMAKO (as opposed to DMAOK, one would think) is hardcoded to use DMA channel 3, 7, or both. It has no tuning parameters and simply sets up the required DMA channel(s) for single mode read transfers. That means there will be a read from memory, and almost certainly no device on the other end that would care about it.
DMAKO offers little control and does not slow down the system nearly as much as DMASLO can, but it does make a clear difference on the test system (the same Alaris Cougar 486 board mentioned above) and noticeably reduces the measured CPU speed.
However, the DMASLO utility is only intended to (drastically) slow down games and the author warns that it likely interferes with the PC’s operation. The DMAKO utility is designed to slow things down but not break anything; it uses DMA channel 3 (or 7) because it has the lowest priority, meaning that floppy access (using DMA channel 2, higher priority than 3) still works.