Date: Thu, 13 Dec 2001 15:14:26 +1100 (EST) From: gjohnson@research.canon.com.au (Greg Johnson) To: freebsd-hackers@FreeBSD.ORG Subject: Bus master DMA problems Message-ID: <20011213041426.77707B7331@brixi.research.canon.com.au>
next in thread | raw e-mail | index | archive | help
Hello, I am working on a FreeBSD device driver for a custom PCI bus device developed by my company. The PCI card has large amounts on memory on it and we are using bus master DMA to get data in and out of memory. The proceedure that I am using is as follows: A.1. The DMA controller on our device is set up for the DMA transfer of memory. A.2. asleep() is called to let the OS know that we are about to wait on an event. A.3. An enable bit is set on the device to start the transfer. A.4. await() is called to get the current process to sleep and wait for the event. A.5. The ISR, upon recipt of an interrupt that indicates that the DMA transfer is complete, calls wakeup() on the ident for the process sleeping, waiting for the DMA transfer. A.6. await() returns. In addition, the memory buffers on the PC host side are initially allocated by a user process, and locked down (wired) buy the device driver so that they a present in physical memory. A bus DMA Tag is created once on driver load that describes the DMA transfers. On a call to read or write: B.1. Memory is locked. B.2. bus_dmamap_sync() is called (PRE*) B.3. bus_dmamap_load() is called B.4. bus_dmamap sync() is called (POST*) B.5. Memory is unlocked. Now, the problem I am experiencing is that memory does not appear to be DMAed correctly. When using the interrupt driver method above, sometimes there are errors in the data written to the device, and sometimes in the data read back from the device. When using a polling approach and dissabling the DMA interrupts, starting the transfer and polling for when the transfer is complete, the system works correctly. Also, when using the interrupt approach described, if I insert a large delay of about 100us (50us does not work) in the ISR at the point when the ISR confirms that the interrupt is the DMA done interrupt, then everything works correctly. The problem sounds a lot like out PCI device is not completing the DMA transfer when the interrupt is raised, but with the polling process, it only seems to take a few (2-8)us before the DMA done interrupt is asserted and the call returns, and in this case everything works. So if anyong out there in FreeBSD guru land has any ideas as to what might be wrong, or things I might of missed in seeting up stuff, I would really appreciate their input. Our systems are x86 (PIIIs and P4s) running FreeBSD 4.4-stable. Thanks. Greg. -- +------------------------------------------------------+ | Do you want to know more? www.geocities.com/worfsom/ | | ..ooOO Greg Johnson OOoo.. | | HW/SW Engineer gjohnson@research.canon.COM.Au | | Canon Information Systems Research Australia (CISRA) | | 1 Thomas Holt Dr., North Ryde, NSW, 2113, Australia | | "I FLEXed my BISON and it went YACC!" - me. | +------------------------------------------------------+ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011213041426.77707B7331>