In the single-buffer strategy, the VDD again determines a DMA request is pending by receiving a command from the application. To avoid copying the data to its own memory space, the VDD calls VDDQueryDMA to determine the source, destination, and other DMA parameters. It then sends the DMA information to the kernel-mode device driver and allows that driver to transfer the data directly from the application's buffer to the device, as shown in the following illustration. The kernel-mode device driver can program the DMA controller through the platform-specific HAL to carry out the transfer or it can use some other means to transfer the data. In the other direction, the VDD can request that the driver transfer data directly from the device to the application's buffer. In either direction, VDDs using this second strategy must call VDDSetDMA to update the DMA state after the transfer is complete.
Direct virtual DMA transfer
Because DMA registers contain physical addresses, a VDD that uses VDDQueryDMA must correctly convert these addresses to Win32 linear addresses in the VDM process address space.
The following illustration shows how the virtual DOS machine can be laid out in memory relative to the VDM process. On an x86 machine, linear zero of the VDM process is the same as 0:0 for DOS. On a nonx86 machine these addresses might be different. The addresses returned by VDDQueryDMA are relative to the DOS 0:0.
Memory Layout for DMA addresses
On an x86 machine, there is no difference between a DMA address, as programmed by the MS-DOS application to the DMA chip, and a Win32 address. On a nonx86 machine, you must add the offset from VDM 0 to DOS 0:0 to convert a DMA address to a Win32 address. To get the offset from VDM to DOS, call GetVDMPointer(0,0,0). On an x86 machine, this call returns zero. On a RISC machine, it returns the difference between VDM 0 and DOS 0:0. Thus, adding GetVDMPointer(0,0,0) to a DMA address always gives the correct Win32 linear pointer, regardless of machine type.