← Documents Documentation/core-api/dma-isa-lpc.rst GitHub 원문 ↗

Linux 6.18.37 · Core API

DMA with ISA and LPC devices

ISA와 LPC device의 legacy DMA controller에서 buffer, channel, lock, transfer 및 suspend 상태를 올바르게 관리하는 방법을 설명합니다.

Source pathDocumentation/core-api/dma-isa-lpc.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

dma-isa-lpc.rst:1-152

ISA DMA는 physical memory의 낮은 16 MB와 channel별 64/128 KiB boundary라는 강한 제약이 있어 `GFP_DMA` 전용 buffer가 필요합니다. 희소한 memory이므로 일찍 allocate하고 오래 유지하는 편이 좋습니다.

Address 변환에는 `isa_virt_to_bus()`가 아닌 generic DMA API를 사용하며 Kconfig는 `ISA_DMA_API`에 의존해야 합니다. 8-bit와 16-bit channel 선택은 hardware capability가 결정합니다.

Controller register 조작은 `claim_dma_lock()`과 `release_dma_lock()` 사이에서 수행하고 처음에는 `clear_dma_ff()`를 호출합니다. 완료 뒤 channel을 disable하고 residue를 검사하며 suspend 동안 사라진 설정은 resume에서 복원합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

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

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

ISA와 LPC device의 DMA

1-10

DMA with ISA and LPC devices (ISA 및 LPC device의 DMA)

저자는 Pierre Ossman <drzeus@drzeus.cx>입니다.

이 문서는 오래된 ISA DMA controller로 DMA transfer를 수행하는 방법을 설명합니다. 오늘날 ISA는 거의 사라졌지만 LPC bus가 같은 DMA system을 사용하므로 이 interface는 상당 기간 유지될 것입니다.

Header와 Kconfig dependency

11-26

Header와 dependency

ISA 방식 DMA에는 다음 두 header를 포함해야 합니다.

#include <linux/dma-mapping.h>
#include <asm/dma.h>

첫 header는 virtual address를 bus address로 변환하는 generic DMA API입니다. 자세한 내용은 `Documentation/core-api/dma-api.rst`를 참고하십시오.

두 번째 header는 ISA DMA transfer 전용 routine을 제공합니다. 모든 platform에 존재하지 않으므로 Kconfig는 `ISA`가 아니라 `ISA_DMA_API`에 의존하도록 구성해야 합니다. 그래야 지원하지 않는 platform에서 driver build를 시도하지 않습니다.

ISA DMA buffer allocation

27-50

Buffer allocation

ISA DMA controller는 접근 가능한 memory에 매우 엄격한 요구 사항이 있으므로 buffer allocation에 각별히 주의해야 합니다. 보통 일반 data structure에서 직접 transfer하지 않고 DMA 전용 buffer가 필요합니다.

DMA 가능한 address space는 physical memory의 가장 낮은 16 MB입니다. 또한 transfer block은 사용하는 channel에 따라 64 KiB 또는 128 KiB인 page boundary를 넘을 수 없습니다.

모든 요구를 만족하는 memory는 `kmalloc()`에 `GFP_DMA` flag를 전달하여 allocate합니다.

ISA DMA memory는 희소합니다. Boot 중에 allocate하는 경우가 아니라면 allocator가 조금 더 노력하되 불필요한 warning을 내지 않도록 `__GFP_RETRY_MAYFAIL`과 `__GFP_NOWARN`도 전달하는 것이 좋습니다.

이 희소성 때문에 buffer를 가능한 한 일찍 allocate하고 driver가 unload될 때까지 해제하지 않는 것이 좋습니다.

Virtual address를 bus address로 변환

51-64

Address translation

Virtual address를 bus address로 변환할 때 normal DMA API를 사용하십시오. 같은 일을 하더라도 `isa_virt_to_bus()`를 사용하면 안 됩니다. 이 함수는 실제로 필요한 `ISA_DMA_API`뿐 아니라 `ISA`에 대한 Kconfig dependency를 요구하기 때문입니다. DMA controller의 기원은 ISA이지만 다른 곳에서도 사용됩니다.

참고로 x86_64의 ISA 관련 DMA API는 과거에 깨져 있었지만 수정되었습니다. 다른 architecture에 문제가 있다면 ISA function으로 되돌아가지 말고 DMA API를 고쳐야 합니다.

8-bit와 16-bit DMA channel

65-83

Channel

일반 ISA DMA controller에는 8개 channel이 있습니다. 아래 네 개는 8-bit transfer용이고 위 네 개는 16-bit transfer용입니다.

실제로는 두 controller로 구성되며 channel 4가 두 번째 controller인 channel 0-3에 DMA access를 제공하는 데 사용됩니다. 따라서 네 개의 16-bit channel 중 실제로 사용할 수 있는 것은 세 개뿐입니다.

다른 기본 resource와 비슷하게 다음 함수로 channel을 요청하고 해제합니다.

extern int request_dma(unsigned int dmanr, const char * device_id);
extern void free_dma(unsigned int dmanr);

16-bit 또는 8-bit transfer 사용 여부는 driver 작성자가 선택하는 것이 아니라 hardware 지원에 달려 있습니다. 명세를 확인하거나 여러 channel을 시험하십시오.

ISA DMA transfer 절차

84-144

Data transfer

이제 실제 DMA transfer 절차입니다.

ISA DMA routine을 사용하기 전에 `claim_dma_lock()`으로 DMA lock을 획득해야 합니다. 일부 DMA operation은 atomic하지 않으므로 한 번에 하나의 driver만 register를 조작할 수 있어야 합니다.

DMA controller를 처음 사용할 때 `clear_dma_ff()`를 호출합니다. 이 함수는 non-atomic operation에 쓰이는 controller 내부 register를 지웁니다. 모든 사용자가 locking function을 지킨다면 한 번만 reset하면 됩니다.

그다음 `set_dma_mode()`로 transfer direction을 알립니다. 현재 선택지는 `DMA_MODE_READ`와 `DMA_MODE_WRITE`입니다.

Transfer 시작 address와 byte 수를 설정합니다. 16-bit transfer의 address는 16-bit 정렬이어야 합니다. Count 단위는 word가 아니라 byte이며 DMA routine이 controller가 이해하는 값으로 필요한 변환을 수행합니다.

마지막으로 DMA channel을 활성화하고 DMA lock을 해제합니다. Transfer가 끝나거나 timeout되면 channel을 다시 비활성화하고 `get_dma_residue()`로 모든 data가 전송되었는지 확인해야 합니다.

전체 순서를 보여 주는 예제입니다.

int flags, residue;

flags = claim_dma_lock();

clear_dma_ff();

set_dma_mode(channel, DMA_MODE_WRITE);
set_dma_addr(channel, phys_addr);
set_dma_count(channel, num_bytes);

dma_enable(channel);

release_dma_lock(flags);

while (!device_done());

flags = claim_dma_lock();

dma_disable(channel);

residue = dma_get_residue(channel);
if (residue != 0)
        printk(KERN_ERR "driver: Incomplete DMA transfer!"
                " %d bytes left!\n", residue);

release_dma_lock(flags);

Suspend와 resume

145-152

Suspend/resume

DMA transfer 진행 중 machine이 suspend되지 않도록 보장하는 것은 driver의 책임입니다. System suspend 시 모든 DMA 설정을 잃으므로 driver가 DMA controller의 특정 state에 의존한다면 resume 때 해당 register를 복원해야 합니다.