The other day I set out to solve a seemingly simple problem: With a DOS extended application, lock down memory buffers using DPMI and use them for bus-mastering (BusLogic SCSI HBA, though the exact device model isn’t really relevant to the problem).
Now, DPMI does not allow querying the physical address of a memory region, although it does have provisions for mapping a given physical memory area. But that doesn’t help here–mapping physical memory is useful for framebuffers where a device memory needs to be mapped so that an application can access it. In my case, I needed the opposite, allowing a bus-mastering device to use already-allocated system memory.
As many readers probably know, VDS (Virtual DMA Services) should solve this problem through the “Scatter/Gather Lock Region” VDS function. The function is presented with a linear address and buffer size, and returns one or more physically contiguous regions together with their physical addresses.
I already had VDS working for low (DOS) memory, but I just could not get it working for “normal” extended memory. It did not matter if I used statically allocated variables placed in the executable, C runtime malloc()
, or direct DPMI memory allocation functions. The VDS call succeeded and filled the result buffer with the same address I passed in, indicating a 1:1 linear:physical mapping, except the memory definitely was not mapped 1:1. So bus-mastering couldn’t work, because the addresses I programmed into the adapter were bogus. But why was this happening?