aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/DMA-ISA-LPC.txt
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2005-09-09 16:10:13 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 17:03:42 -0400
commitddb99f3d35b178f0715aab2f9d9ab25f61814347 (patch)
tree45b9f3dab3204555465216dd18269f170c1e6429 /Documentation/DMA-ISA-LPC.txt
parent754c79768eed257dabd922b85cb9271822e50794 (diff)
[PATCH] ISA DMA API documentation
Documentation for how the ISA DMA controller is handled in the kernel. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'Documentation/DMA-ISA-LPC.txt')
-rw-r--r--Documentation/DMA-ISA-LPC.txt151
1 files changed, 151 insertions, 0 deletions
diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt
new file mode 100644
index 000000000000..705f6be92bdb
--- /dev/null
+++ b/Documentation/DMA-ISA-LPC.txt
@@ -0,0 +1,151 @@
1 DMA with ISA and LPC devices
2 ============================
3
4 Pierre Ossman <drzeus@drzeus.cx>
5
6This document describes how to do DMA transfers using the old ISA DMA
7controller. Even though ISA is more or less dead today the LPC bus
8uses the same DMA system so it will be around for quite some time.
9
10Part I - Headers and dependencies
11---------------------------------
12
13To do ISA style DMA you need to include two headers:
14
15#include <linux/dma-mapping.h>
16#include <asm/dma.h>
17
18The first is the generic DMA API used to convert virtual addresses to
19physical addresses (see Documentation/DMA-API.txt for details).
20
21The second contains the routines specific to ISA DMA transfers. Since
22this is not present on all platforms make sure you construct your
23Kconfig to be dependent on ISA_DMA_API (not ISA) so that nobody tries
24to build your driver on unsupported platforms.
25
26Part II - Buffer allocation
27---------------------------
28
29The ISA DMA controller has some very strict requirements on which
30memory it can access so extra care must be taken when allocating
31buffers.
32
33(You usually need a special buffer for DMA transfers instead of
34transferring directly to and from your normal data structures.)
35
36The DMA-able address space is the lowest 16 MB of _physical_ memory.
37Also the transfer block may not cross page boundaries (which are 64
38or 128 KiB depending on which channel you use).
39
40In order to allocate a piece of memory that satisfies all these
41requirements you pass the flag GFP_DMA to kmalloc.
42
43Unfortunately the memory available for ISA DMA is scarce so unless you
44allocate the memory during boot-up it's a good idea to also pass
45__GFP_REPEAT and __GFP_NOWARN to make the allocater try a bit harder.
46
47(This scarcity also means that you should allocate the buffer as
48early as possible and not release it until the driver is unloaded.)
49
50Part III - Address translation
51------------------------------
52
53To translate the virtual address to a physical use the normal DMA
54API. Do _not_ use isa_virt_to_phys() even though it does the same
55thing. The reason for this is that the function isa_virt_to_phys()
56will require a Kconfig dependency to ISA, not just ISA_DMA_API which
57is really all you need. Remember that even though the DMA controller
58has its origins in ISA it is used elsewhere.
59
60Note: x86_64 had a broken DMA API when it came to ISA but has since
61been fixed. If your arch has problems then fix the DMA API instead of
62reverting to the ISA functions.
63
64Part IV - Channels
65------------------
66
67A normal ISA DMA controller has 8 channels. The lower four are for
688-bit transfers and the upper four are for 16-bit transfers.
69
70(Actually the DMA controller is really two separate controllers where
71channel 4 is used to give DMA access for the second controller (0-3).
72This means that of the four 16-bits channels only three are usable.)
73
74You allocate these in a similar fashion as all basic resources:
75
76extern int request_dma(unsigned int dmanr, const char * device_id);
77extern void free_dma(unsigned int dmanr);
78
79The ability to use 16-bit or 8-bit transfers is _not_ up to you as a
80driver author but depends on what the hardware supports. Check your
81specs or test different channels.
82
83Part V - Transfer data
84----------------------
85
86Now for the good stuff, the actual DMA transfer. :)
87
88Before you use any ISA DMA routines you need to claim the DMA lock
89using claim_dma_lock(). The reason is that some DMA operations are
90not atomic so only one driver may fiddle with the registers at a
91time.
92
93The first time you use the DMA controller you should call
94clear_dma_ff(). This clears an internal register in the DMA
95controller that is used for the non-atomic operations. As long as you
96(and everyone else) uses the locking functions then you only need to
97reset this once.
98
99Next, you tell the controller in which direction you intend to do the
100transfer using set_dma_mode(). Currently you have the options
101DMA_MODE_READ and DMA_MODE_WRITE.
102
103Set the address from where the transfer should start (this needs to
104be 16-bit aligned for 16-bit transfers) and how many bytes to
105transfer. Note that it's _bytes_. The DMA routines will do all the
106required translation to values that the DMA controller understands.
107
108The final step is enabling the DMA channel and releasing the DMA
109lock.
110
111Once the DMA transfer is finished (or timed out) you should disable
112the channel again. You should also check get_dma_residue() to make
113sure that all data has been transfered.
114
115Example:
116
117int flags, residue;
118
119flags = claim_dma_lock();
120
121clear_dma_ff();
122
123set_dma_mode(channel, DMA_MODE_WRITE);
124set_dma_addr(channel, phys_addr);
125set_dma_count(channel, num_bytes);
126
127dma_enable(channel);
128
129release_dma_lock(flags);
130
131while (!device_done());
132
133flags = claim_dma_lock();
134
135dma_disable(channel);
136
137residue = dma_get_residue(channel);
138if (residue != 0)
139 printk(KERN_ERR "driver: Incomplete DMA transfer!"
140 " %d bytes left!\n", residue);
141
142release_dma_lock(flags);
143
144Part VI - Suspend/resume
145------------------------
146
147It is the driver's responsibility to make sure that the machine isn't
148suspended while a DMA transfer is in progress. Also, all DMA settings
149are lost when the system suspends so if your driver relies on the DMA
150controller being in a certain state then you have to restore these
151registers upon resume.