Messages in this thread | | | Date | Thu, 16 Mar 2000 11:48:17 -0500 | From | John Wilson <> | Subject | Re: DMA to user space |
| |
On Thu, Mar 16, 2000 at 08:22:38AM -0500, Richard B. Johnson wrote: > No. Not a "user-buffer". It may be possible to memory-map something that's > DMA..able to user space, but even that's not guaranteed. To have something > DMA..able in the ix86 machines, it needs to be: > > (1) Physical, below 16 Megabytes > (2) DATA alignment must be such that a 64k block is not crossed > during a DMA transfer. The ix86 machines use a page register > to access 64k pages. > (3) You need access to the DMA controller which the kernel isn't > going to give you, without a fight iopl(3), etc., from user- > space.
No no, these requirements are for ISA DMA, not DMA in general. I'm using a PCI device, so there are no address restrictions (on x86 anyway, I dunno how PCI works on CPUs with >32 addr bits), and it has its own DMA paging registers so it doesn't require a contiguous buffer either. The buffer just has to be locked in place, which sounds like mlock() would be my friend.
Also, my driver is a real driver, it doesn't run in user space. I just want it to be able to set the device up so that the DMA buffer (*only*) is in user space, and let 'er rip.
> > The advantage of doing the DMA in user space is that arbitrarily many devices > > (potentially using different drivers) could be connected to the same 4 > > MB user buffer. Not many users will need this, but it works great in the > > DOS version of the application and if possible I'd like to avoid having to > > explain to customers why moving to the "better" OS means losing features. > > > > DMA has nothing at all to do with this. DMA transfers data between > physical areas, memory-to-ports, ports-to-memory, or (one channel) > memory-to-memory. They are not "connected-to" some common buffer.
Again, you're talking about 8237 DMA channels on the ISA bus. Nothing to do with my device. Its mapping registers have been set up so that all of the random DMA it does will fall into a particular 4 MB buffer. So it's "connected to" this buffer. I want to connect multiple devices (not necessarily all using the same driver, since these bus bridges are made by three different vendors) to the *same* buffer, which I can't do if the buffer is hidden inside one of those drivers. That's why I want it to use the user's buffer.
> If you have N devices that are memory-mapped to the same physical > address, they will interfere.
Clearly, but it's not a memory-mapped device, it's a bus master which wants to do DMA to random addresses in the user's 4 MB buffer, on its own initiative. I'm talking about ownership of the buffer to which it does the random DMA, which is plain old memory.
> If you have N devices that can copy > their data from a port to a shared buffer then, in principle, you > can use these devices together if you can synchronize the copying > operation. You can copy to/from ports without ever using DMA. > > This means that you can copy directly to/from any user buffer > you want. You don't need to even know its physical address.
No I can't. The point of this device is to connect random unknown 1970s DMA bus master devices to the PC. My application is a "black box" emulator, its job is to do what it's told and let the emulated OS be in charge of the actual devices on the other side of the bus bridge. It has no knowledge of whether what the emulated system is going to do will cause DMA to happen, or to what address(es), or whether it will read or write. So I *can't* have private buffers for each device which are copied to/from the user's buffer.
I can't synchronize things between transfers, because again I have no way of knowing whether a transfer is going on, and it's perfectly possible (actually very likely) to have more than one transfer in progress at any given time. All DMA devices on the foreign bus are bus masters so they have their own buf addr and word count registers, and since they're "black boxes" I don't know the meaning of the command/status values that I pass back and forth between the emulated OS and the hardware, so I don't know what they will make the foreign devices do.
Anyway as I said in my original message, I've already got the driver more or less working (well, readl() seems to be returning what should be "impossible" values some of the time) by using a driver-owned buffer which the user job mmaps into a window. But I consider that a kludge. I'm a big fan of doing what I actually *mean* whenever possible, rather than living with some twisted hack that happens to work *most* of the time, so I'd prefer to simulate the effect of doing DMA into the user's buffer, by *really* doing DMA into the user's buffer!
So, back to my question: is it possible to place a DMA buffer in user space? Is mlock() enough to hold the user's pages in place? Does virt_to_phys() work on user addresses passed as argp to ioctl(), or does it only work on get_free_page() addresses? I'm used to systems with entirely separate address spaces for kernel mode and user mode, so I don't know how Linux gets around the that in the x86, does it map a window into user space or does it just partition a single 32-bit address space so kernel mode gets the low end and user space gets the rest? Or would I have to fiddle with the user's page table directly?
John Wilson D Bit
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |