Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
arm
kernel
dma.c
Go to the documentation of this file.
1
/*
2
* linux/arch/arm/kernel/dma.c
3
*
4
* Copyright (C) 1995-2000 Russell King
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*
10
* Front-end to the DMA handling. This handles the allocation/freeing
11
* of DMA channels, and provides a unified interface to the machines
12
* DMA facilities.
13
*/
14
#include <linux/module.h>
15
#include <
linux/init.h
>
16
#include <
linux/spinlock.h
>
17
#include <linux/errno.h>
18
#include <
linux/scatterlist.h
>
19
#include <
linux/seq_file.h
>
20
#include <
linux/proc_fs.h
>
21
22
#include <asm/dma.h>
23
24
#include <
asm/mach/dma.h
>
25
26
DEFINE_RAW_SPINLOCK
(dma_spin_lock);
27
EXPORT_SYMBOL
(dma_spin_lock);
28
29
static
dma_t
*
dma_chan
[
MAX_DMA_CHANNELS
];
30
31
static
inline
dma_t
*
dma_channel
(
unsigned
int
chan
)
32
{
33
if
(chan >=
MAX_DMA_CHANNELS
)
34
return
NULL
;
35
36
return
dma_chan[chan];
37
}
38
39
int
__init
isa_dma_add
(
unsigned
int
chan,
dma_t
*
dma
)
40
{
41
if
(!dma->
d_ops
)
42
return
-
EINVAL
;
43
44
sg_init_table
(&dma->
buf
, 1);
45
46
if
(dma_chan[chan])
47
return
-
EBUSY
;
48
dma_chan[chan] =
dma
;
49
return
0;
50
}
51
52
/*
53
* Request DMA channel
54
*
55
* On certain platforms, we have to allocate an interrupt as well...
56
*/
57
int
request_dma
(
unsigned
int
chan,
const
char
*
device_id
)
58
{
59
dma_t
*
dma
=
dma_channel
(chan);
60
int
ret
;
61
62
if
(!dma)
63
goto
bad_dma;
64
65
if
(
xchg
(&dma->
lock
, 1) != 0)
66
goto
busy
;
67
68
dma->
device_id
=
device_id
;
69
dma->
active
= 0;
70
dma->
invalid
= 1;
71
72
ret = 0;
73
if
(dma->
d_ops
->request)
74
ret = dma->
d_ops
->request(chan, dma);
75
76
if
(ret)
77
xchg
(&dma->
lock
, 0);
78
79
return
ret
;
80
81
bad_dma:
82
printk
(
KERN_ERR
"dma: trying to allocate DMA%d\n"
, chan);
83
return
-
EINVAL
;
84
85
busy
:
86
return
-
EBUSY
;
87
}
88
EXPORT_SYMBOL
(
request_dma
);
89
90
/*
91
* Free DMA channel
92
*
93
* On certain platforms, we have to free interrupt as well...
94
*/
95
void
free_dma
(
unsigned
int
chan)
96
{
97
dma_t
*
dma
=
dma_channel
(chan);
98
99
if
(!dma)
100
goto
bad_dma;
101
102
if
(dma->
active
) {
103
printk
(
KERN_ERR
"dma%d: freeing active DMA\n"
, chan);
104
dma->
d_ops
->disable(chan, dma);
105
dma->
active
= 0;
106
}
107
108
if
(
xchg
(&dma->
lock
, 0) != 0) {
109
if
(dma->
d_ops
->free)
110
dma->
d_ops
->free(chan, dma);
111
return
;
112
}
113
114
printk
(
KERN_ERR
"dma%d: trying to free free DMA\n"
, chan);
115
return
;
116
117
bad_dma:
118
printk
(
KERN_ERR
"dma: trying to free DMA%d\n"
, chan);
119
}
120
EXPORT_SYMBOL
(
free_dma
);
121
122
/* Set DMA Scatter-Gather list
123
*/
124
void
set_dma_sg
(
unsigned
int
chan,
struct
scatterlist
*
sg
,
int
nr_sg)
125
{
126
dma_t
*
dma
=
dma_channel
(chan);
127
128
if
(dma->
active
)
129
printk
(
KERN_ERR
"dma%d: altering DMA SG while "
130
"DMA active\n"
, chan);
131
132
dma->
sg
=
sg
;
133
dma->
sgcount
= nr_sg;
134
dma->
invalid
= 1;
135
}
136
EXPORT_SYMBOL
(
set_dma_sg
);
137
138
/* Set DMA address
139
*
140
* Copy address to the structure, and set the invalid bit
141
*/
142
void
__set_dma_addr
(
unsigned
int
chan,
void
*
addr
)
143
{
144
dma_t
*
dma
=
dma_channel
(chan);
145
146
if
(dma->
active
)
147
printk
(
KERN_ERR
"dma%d: altering DMA address while "
148
"DMA active\n"
, chan);
149
150
dma->
sg
=
NULL
;
151
dma->
addr
=
addr
;
152
dma->
invalid
= 1;
153
}
154
EXPORT_SYMBOL
(
__set_dma_addr
);
155
156
/* Set DMA byte count
157
*
158
* Copy address to the structure, and set the invalid bit
159
*/
160
void
set_dma_count
(
unsigned
int
chan,
unsigned
long
count
)
161
{
162
dma_t
*
dma
=
dma_channel
(chan);
163
164
if
(dma->
active
)
165
printk
(
KERN_ERR
"dma%d: altering DMA count while "
166
"DMA active\n"
, chan);
167
168
dma->
sg
=
NULL
;
169
dma->
count
=
count
;
170
dma->
invalid
= 1;
171
}
172
EXPORT_SYMBOL
(
set_dma_count
);
173
174
/* Set DMA direction mode
175
*/
176
void
set_dma_mode
(
unsigned
int
chan,
unsigned
int
mode
)
177
{
178
dma_t
*
dma
=
dma_channel
(chan);
179
180
if
(dma->
active
)
181
printk
(
KERN_ERR
"dma%d: altering DMA mode while "
182
"DMA active\n"
, chan);
183
184
dma->
dma_mode
=
mode
;
185
dma->
invalid
= 1;
186
}
187
EXPORT_SYMBOL
(
set_dma_mode
);
188
189
/* Enable DMA channel
190
*/
191
void
enable_dma
(
unsigned
int
chan)
192
{
193
dma_t
*
dma
=
dma_channel
(chan);
194
195
if
(!dma->
lock
)
196
goto
free_dma
;
197
198
if
(dma->
active
== 0) {
199
dma->
active
= 1;
200
dma->
d_ops
->enable(chan, dma);
201
}
202
return
;
203
204
free_dma
:
205
printk
(
KERN_ERR
"dma%d: trying to enable free DMA\n"
, chan);
206
BUG
();
207
}
208
EXPORT_SYMBOL
(
enable_dma
);
209
210
/* Disable DMA channel
211
*/
212
void
disable_dma
(
unsigned
int
chan)
213
{
214
dma_t
*
dma
=
dma_channel
(chan);
215
216
if
(!dma->
lock
)
217
goto
free_dma
;
218
219
if
(dma->
active
== 1) {
220
dma->
active
= 0;
221
dma->
d_ops
->disable(chan, dma);
222
}
223
return
;
224
225
free_dma
:
226
printk
(
KERN_ERR
"dma%d: trying to disable free DMA\n"
, chan);
227
BUG
();
228
}
229
EXPORT_SYMBOL
(
disable_dma
);
230
231
/*
232
* Is the specified DMA channel active?
233
*/
234
int
dma_channel_active
(
unsigned
int
chan)
235
{
236
dma_t
*
dma
=
dma_channel
(chan);
237
return
dma->
active
;
238
}
239
EXPORT_SYMBOL
(
dma_channel_active
);
240
241
void
set_dma_page
(
unsigned
int
chan,
char
pagenr)
242
{
243
printk
(
KERN_ERR
"dma%d: trying to set_dma_page\n"
, chan);
244
}
245
EXPORT_SYMBOL
(
set_dma_page
);
246
247
void
set_dma_speed
(
unsigned
int
chan,
int
cycle_ns)
248
{
249
dma_t
*
dma
=
dma_channel
(chan);
250
int
ret
= 0;
251
252
if
(dma->
d_ops
->setspeed)
253
ret = dma->
d_ops
->setspeed(chan, dma, cycle_ns);
254
dma->
speed
=
ret
;
255
}
256
EXPORT_SYMBOL
(
set_dma_speed
);
257
258
int
get_dma_residue
(
unsigned
int
chan)
259
{
260
dma_t
*
dma
=
dma_channel
(chan);
261
int
ret
= 0;
262
263
if
(dma->
d_ops
->residue)
264
ret = dma->
d_ops
->residue(chan, dma);
265
266
return
ret
;
267
}
268
EXPORT_SYMBOL
(
get_dma_residue
);
269
270
#ifdef CONFIG_PROC_FS
271
static
int
proc_dma_show(
struct
seq_file
*
m
,
void
*
v
)
272
{
273
int
i
;
274
275
for
(i = 0 ; i <
MAX_DMA_CHANNELS
; i++) {
276
dma_t
*
dma
=
dma_channel
(i);
277
if
(dma && dma->
lock
)
278
seq_printf
(m,
"%2d: %s\n"
, i, dma->
device_id
);
279
}
280
return
0;
281
}
282
283
static
int
proc_dma_open(
struct
inode
*
inode
,
struct
file
*
file
)
284
{
285
return
single_open
(file, proc_dma_show,
NULL
);
286
}
287
288
static
const
struct
file_operations
proc_dma_operations = {
289
.
open
= proc_dma_open,
290
.read =
seq_read
,
291
.llseek =
seq_lseek
,
292
.release =
single_release
,
293
};
294
295
static
int
__init
proc_dma_init(
void
)
296
{
297
proc_create(
"dma"
, 0,
NULL
, &proc_dma_operations);
298
return
0;
299
}
300
301
__initcall
(proc_dma_init);
302
#endif
Generated on Thu Jan 10 2013 12:55:38 for Linux Kernel by
1.8.2