Skip site navigation (1)Skip section navigation (2)
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>