FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
SmartisanOS_Kernel_Source/kernel/dma.c at master · lvlinuxfeng/SmartisanOS_Kernel_Source · GitHub
lvlinuxfeng
SmartisanOS_Kernel_Source
Repository navigation
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
SmartisanOS_Kernel_Source
/
kernel
/
dma.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
160 lines (129 loc) · 3.58 KB
Breadcrumbs
SmartisanOS_Kernel_Source
/
kernel
/
dma.c
Copy path
File metadata and controls
160 lines (129 loc) · 3.58 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
*
* Written by Hennus Bergman, 1992.
*
* 1994/12/26: Changes by Alex Nash to fix a minor bug in /proc/dma.
* In the previous version the reported device could end up being wrong,
* if a device requested a DMA channel that was already in use.
* [It also happened to remove the sizeof(char *) == sizeof(int)
* assumption introduced because of those /proc/dma patches. -- Hennus]
*/
#include
<linux/export.h>
#include
<linux/kernel.h>
#include
<linux/errno.h>
#include
<linux/spinlock.h>
#include
<linux/string.h>
#include
<linux/seq_file.h>
#include
<linux/proc_fs.h>
#include
<linux/init.h>
#include
<asm/dma.h>
/* A note on resource allocation:
*
* All drivers needing DMA channels, should allocate and release them
* through the public routines `request_dma()' and `free_dma()'.
*
* In order to avoid problems, all processes should allocate resources in
* the same sequence and release them in the reverse order.
*
* So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
* When releasing them, first release the DMA, then release the IRQ.
* If you don't, you may cause allocation requests to fail unnecessarily.
* This doesn't really matter now, but it will once we get real semaphores
* in the kernel.
*/
DEFINE_SPINLOCK
(
dma_spin_lock
);
/*
* If our port doesn't define this it has no PC like DMA
*/
#ifdef
MAX_DMA_CHANNELS
/* Channel n is busy iff dma_chan_busy[n].lock != 0.
* DMA0 used to be reserved for DRAM refresh, but apparently not any more...
* DMA4 is reserved for cascading.
*/
struct
dma_chan
{
int
lock
;
const
char
*
device_id
;
};
static
struct
dma_chan
dma_chan_busy
[
MAX_DMA_CHANNELS
]
=
{
[
4
]
=
{
1
,
"cascade"
},
};
/**
* request_dma - request and reserve a system DMA channel
* @dmanr: DMA channel number
* @device_id: reserving device ID string, used in /proc/dma
*/
int
request_dma
(
unsigned
int
dmanr
,
const
char
*
device_id
)
{
if
(
dmanr
>=
MAX_DMA_CHANNELS
)
return
-
EINVAL
;
if
(
xchg
(
&
dma_chan_busy
[
dmanr
].
lock
,
1
)
!=
0
)
return
-
EBUSY
;
dma_chan_busy
[
dmanr
].
device_id
=
device_id
;
/* old flag was 0, now contains 1 to indicate busy */
return
0
;
}
/* request_dma */
/**
* free_dma - free a reserved system DMA channel
* @dmanr: DMA channel number
*/
void
free_dma
(
unsigned
int
dmanr
)
{
if
(
dmanr
>=
MAX_DMA_CHANNELS
) {
printk
(
KERN_WARNING
"Trying to free DMA%d\n"
,
dmanr
);
return
;
}
if
(
xchg
(
&
dma_chan_busy
[
dmanr
].
lock
,
0
)
==
0
) {
printk
(
KERN_WARNING
"Trying to free free DMA%d\n"
,
dmanr
);
return
;
}
}
/* free_dma */
#else
int
request_dma
(
unsigned
int
dmanr
,
const
char
*
device_id
)
{
return
-
EINVAL
;
}
void
free_dma
(
unsigned
int
dmanr
)
{
}
#endif
#ifdef
CONFIG_PROC_FS
#ifdef
MAX_DMA_CHANNELS
static
int
proc_dma_show
(
struct
seq_file
*
m
,
void
*
v
)
{
int
i
;
for
(
i
=
0
;
i
<
MAX_DMA_CHANNELS
;
i
++
) {
if
(
dma_chan_busy
[
i
].
lock
) {
seq_printf
(
m
,
"%2d: %s\n"
,
i
,
dma_chan_busy
[
i
].
device_id
);
}
}
return
0
;
}
#else
static
int
proc_dma_show
(
struct
seq_file
*
m
,
void
*
v
)
{
seq_puts
(
m
,
"No DMA\n"
);
return
0
;
}
#endif
/* MAX_DMA_CHANNELS */
static
int
proc_dma_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
proc_dma_show
,
NULL
);
}
static
const
struct
file_operations
proc_dma_operations
=
{
.
open
=
proc_dma_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
};
static
int
__init
proc_dma_init
(
void
)
{
proc_create
(
"dma"
,
0
,
NULL
,
&
proc_dma_operations
);
return
0
;
}
__initcall
(
proc_dma_init
);
#endif
EXPORT_SYMBOL
(
request_dma
);
EXPORT_SYMBOL
(
free_dma
);
EXPORT_SYMBOL
(
dma_spin_lock
);
Back
|
FazBrowse Home
|
New Git URL