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.
|