Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Q&As > Hardware & Drivers > Apple Hardware >

PrepareMemoryForIO in the NewWorld


Q: I'm writing a device driver that controls DMA hardware. My driver fails when running on NewWorld machines, such as the iMac. What's going on?

A: The most likely answer is that you are not calling PrepareMemoryForIO correctly. Specifically, you must call PrepareMemoryForIO on your DMA buffers, even if virtual memory is off.

Prior to the introduction of NewWorld, all PCI machines had a one-to-one mapping between logical addresses and physical addresses when VM was off. So the logical address used by software to access a buffer is the same as the physical address used by DMA hardware to access that buffer. On NewWorld machines, this is not the case.

How do you cope with this? You must call PrepareMemoryForIO to map the logical address of the buffer to a physical address, which you can then pass to your DMA engine. PrepareMemoryForIO does whatever is necessary to ensure that the I/O transfer is coordinated with the memory system. This includes, but is not limited to, mapping logical addresses to physical addresses, flushing memory caches, and marking memory pages as non-cacheable. It must always be called for a DMA buffer, regardless of whether VM is turned on or off.

It's likely that you already have code to call PrepareMemoryForIO correctly, otherwise your card would not work when virtual memory is enabled. All you have to do is remove your check for the presence of VM.

Note:
Even prior to the introduction of NewWorld, PrepareMemoryForIO was always required for DMA buffers. However this bug is much more subtle and it's likely that you missed it. In addition to mapping logical addresses to physical addresses, PrepareMemoryForIO also guarantees consistency between the memory caches and main memory. Most, but not all, PCI machines are cache-coherent (the hardware guarantees that the memory caches are synchronized with main memory). On the non-cache-coherent machines, PrepareMemoryForIO takes whatever steps are necessary to keep the memory caches synchronized with the DMA transfer. Typically, this involves marking the buffer's pages as uncacheable. By not calling PrepareMemoryForIO, you run the risk of getting stale data out of a memory cache.

For more information about memory caches on the Macintosh, see Technote HW 06 Cache as Cache Can.


Note:
The requirement to prepare memory before doing a DMA transfer is not new. Technote ME 09 Coping with VM and Memory Mappings documents a similar requirement for the 68K driver model, although 68K drivers use LockMemory and GetPhysical rather than PrepareMemoryForIO.

For more information about PrepareMemoryForIO, see:


For more information about the NewWorld ROM architecture, see the iMac Developer Note.

[Dec 07 1998]