>> while (fewer than n samples copied) >> DMASYNC_POSTREAD for sample at offset o > That should be PREREAD (to make sure the dma'd data is visible for > the cpu) >> read sample at offset o > and teh POSTREAD should be here
>> if value is "impossible", break > missig PREWRITE here >> set sample at offset o to "impossible" value >> DMASYNC_PREWRITE for sample at offset o > and this should be POSTWRITE > See the example in the -current man page: This looks a lot like the example in the 8.0 manpage, which did not help much because my use case does not match its very well: > An example of using bus_dmamap_sync(), involving > multiple read-write use of a single mapping might look > like this: I'm not doing read/write DMA. DMA never transfers from memory to the device. (Well, I suppose it does to a small extent, in that the device reads buffer descriptors. But the buffer descriptors are set up once and never touched afterwards; the code snippet I posted is not writing to them.) The hardware is DMAing into the memory, and nothing else. The driver reads the memory and immediately writes it again, to be read by the driver some later time, possibly being overwritten by DMA in between. So an example that says "do write DMA" is not directly applicable. The example makes it look as though read DMA (device->memory) needs to be bracketed by PREREAD and POSTREAD and write DMA by PREWRITE and POSTWRITE. If that were what I'm doing, it would be straightforward. Instead, I have DMA and the driver both writing memory, but only the driver ever reading it. Your placement for PREREAD and POSTREAD confuses me because it doesn't match the example. The example says /* invalidate soon-to-be-stale cache blocks */ bus_dmamap_sync(..., BUS_DMASYNC_PREREAD); [ do read DMA ] /* copy from bounce */ bus_dmamap_sync(..., BUS_DMASYNC_POSTREAD); /* read data now in driver-provided buffer */ [ computation ] /* data to be written now in driver-provided buffer */ /* flush write buffers and writeback, copy to bounce */ bus_dmamap_sync(..., BUS_DMASYNC_PREWRITE); [ do write DMA ] /* probably a no-op, but provided for consistency */ bus_dmamap_sync(..., BUS_DMASYNC_POSTWRITE); but what your changes would have my driver doing is [read-direction DMA might happen here] PREREAD driver reads data from driver-provided buffer POSTREAD [read-direction DMA might happen here] PREWRITE driver writes data to driver-provided buffer POSTWRITE [read-direction DMA might happen here] The conceptual paradigm is - at attach time: allocate, set up, and load the mapping - at open time: tell hardware to start DMAing - at read time (ie, repeatedly): driver reads buffer to see how much has been overwritten by DMA, copying the overwritten portion out and immediately resetting it to the pre-overwrite data, to be overwritten again later - at close tiem: tell hardware to stop DMAing The map is never unloaded; the driver is not detachable. The system has no use case for that, so I saw no point in putting time into it. The code I quoted is the "at read time" part. My guess based on the manpage's example and what you've written is that I need while (fewer than n samples copied) POSTWRITE POSTREAD read sample from buffer if sample isn't "impossible" write "impossible" value to buffer PREWRITE PREREAD if sample is "impossible", break because some aspects of "write", and relatively normal "read", are happening outside that code segment. But this is different enough from what you said (and possibly not well-paired - should the PREWRITE be outside the if?) that now I'm possibly even less sure of myself. I could just try different permutations in the hope of finding something that works, but that strikes me as one of the worst possible ways to do it; I would prefer to understand the paradigm enough to get it right. I am not concerned about the race between pushing the driver-written value to the buffer and DMA overwriting it; provided the driver's write gets pushed reasonably promptly, this will happen only in error conditions like userland ignoring the device for too long - it takes the hardware multiple seconds to wrap around the ring buffer. > I always have to look up the direction, but READ is when CPU reads > data provided by the device. Yes: READ corresponds to read() and WRITE to write(). One of the things that confuses me is that I have no write-direction DMA going on at all; all the DMA is in the read direction. But there is a driver write to the buffer that is, to put it loosely, half of a write DMA operation (the "host writes the buffer" half). /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTML mo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B