Commit cf3e43dbe0cc4a7ee7f6ab1bb5231dcfda164e02
Committed by
Linus Torvalds
1 parent
5785c95bae
[PATCH] cdev documentation
Add some documentation comments for the cdev interface. Signed-off-by: Jonathan Corbet <corbet@lwn.net> Cc: Rolf Eike Beer <eike-kernel@sf-tec.de> Acked-by: "Randy.Dunlap" <rdunlap@xenotime.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 2 changed files with 64 additions and 0 deletions Inline Diff
Documentation/DocBook/kernel-api.tmpl
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" | 2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" |
3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> | 3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> |
4 | 4 | ||
5 | <book id="LinuxKernelAPI"> | 5 | <book id="LinuxKernelAPI"> |
6 | <bookinfo> | 6 | <bookinfo> |
7 | <title>The Linux Kernel API</title> | 7 | <title>The Linux Kernel API</title> |
8 | 8 | ||
9 | <legalnotice> | 9 | <legalnotice> |
10 | <para> | 10 | <para> |
11 | This documentation is free software; you can redistribute | 11 | This documentation is free software; you can redistribute |
12 | it and/or modify it under the terms of the GNU General Public | 12 | it and/or modify it under the terms of the GNU General Public |
13 | License as published by the Free Software Foundation; either | 13 | License as published by the Free Software Foundation; either |
14 | version 2 of the License, or (at your option) any later | 14 | version 2 of the License, or (at your option) any later |
15 | version. | 15 | version. |
16 | </para> | 16 | </para> |
17 | 17 | ||
18 | <para> | 18 | <para> |
19 | This program is distributed in the hope that it will be | 19 | This program is distributed in the hope that it will be |
20 | useful, but WITHOUT ANY WARRANTY; without even the implied | 20 | useful, but WITHOUT ANY WARRANTY; without even the implied |
21 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 21 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
22 | See the GNU General Public License for more details. | 22 | See the GNU General Public License for more details. |
23 | </para> | 23 | </para> |
24 | 24 | ||
25 | <para> | 25 | <para> |
26 | You should have received a copy of the GNU General Public | 26 | You should have received a copy of the GNU General Public |
27 | License along with this program; if not, write to the Free | 27 | License along with this program; if not, write to the Free |
28 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 28 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
29 | MA 02111-1307 USA | 29 | MA 02111-1307 USA |
30 | </para> | 30 | </para> |
31 | 31 | ||
32 | <para> | 32 | <para> |
33 | For more details see the file COPYING in the source | 33 | For more details see the file COPYING in the source |
34 | distribution of Linux. | 34 | distribution of Linux. |
35 | </para> | 35 | </para> |
36 | </legalnotice> | 36 | </legalnotice> |
37 | </bookinfo> | 37 | </bookinfo> |
38 | 38 | ||
39 | <toc></toc> | 39 | <toc></toc> |
40 | 40 | ||
41 | <chapter id="Basics"> | 41 | <chapter id="Basics"> |
42 | <title>Driver Basics</title> | 42 | <title>Driver Basics</title> |
43 | <sect1><title>Driver Entry and Exit points</title> | 43 | <sect1><title>Driver Entry and Exit points</title> |
44 | !Iinclude/linux/init.h | 44 | !Iinclude/linux/init.h |
45 | </sect1> | 45 | </sect1> |
46 | 46 | ||
47 | <sect1><title>Atomic and pointer manipulation</title> | 47 | <sect1><title>Atomic and pointer manipulation</title> |
48 | !Iinclude/asm-i386/atomic.h | 48 | !Iinclude/asm-i386/atomic.h |
49 | !Iinclude/asm-i386/unaligned.h | 49 | !Iinclude/asm-i386/unaligned.h |
50 | </sect1> | 50 | </sect1> |
51 | 51 | ||
52 | <sect1><title>Delaying, scheduling, and timer routines</title> | 52 | <sect1><title>Delaying, scheduling, and timer routines</title> |
53 | !Iinclude/linux/sched.h | 53 | !Iinclude/linux/sched.h |
54 | !Ekernel/sched.c | 54 | !Ekernel/sched.c |
55 | !Ekernel/timer.c | 55 | !Ekernel/timer.c |
56 | </sect1> | 56 | </sect1> |
57 | <sect1><title>High-resolution timers</title> | 57 | <sect1><title>High-resolution timers</title> |
58 | !Iinclude/linux/ktime.h | 58 | !Iinclude/linux/ktime.h |
59 | !Iinclude/linux/hrtimer.h | 59 | !Iinclude/linux/hrtimer.h |
60 | !Ekernel/hrtimer.c | 60 | !Ekernel/hrtimer.c |
61 | </sect1> | 61 | </sect1> |
62 | <sect1><title>Workqueues and Kevents</title> | 62 | <sect1><title>Workqueues and Kevents</title> |
63 | !Ekernel/workqueue.c | 63 | !Ekernel/workqueue.c |
64 | </sect1> | 64 | </sect1> |
65 | <sect1><title>Internal Functions</title> | 65 | <sect1><title>Internal Functions</title> |
66 | !Ikernel/exit.c | 66 | !Ikernel/exit.c |
67 | !Ikernel/signal.c | 67 | !Ikernel/signal.c |
68 | !Iinclude/linux/kthread.h | 68 | !Iinclude/linux/kthread.h |
69 | !Ekernel/kthread.c | 69 | !Ekernel/kthread.c |
70 | </sect1> | 70 | </sect1> |
71 | 71 | ||
72 | <sect1><title>Kernel objects manipulation</title> | 72 | <sect1><title>Kernel objects manipulation</title> |
73 | <!-- | 73 | <!-- |
74 | X!Iinclude/linux/kobject.h | 74 | X!Iinclude/linux/kobject.h |
75 | --> | 75 | --> |
76 | !Elib/kobject.c | 76 | !Elib/kobject.c |
77 | </sect1> | 77 | </sect1> |
78 | 78 | ||
79 | <sect1><title>Kernel utility functions</title> | 79 | <sect1><title>Kernel utility functions</title> |
80 | !Iinclude/linux/kernel.h | 80 | !Iinclude/linux/kernel.h |
81 | !Ekernel/printk.c | 81 | !Ekernel/printk.c |
82 | !Ekernel/panic.c | 82 | !Ekernel/panic.c |
83 | !Ekernel/sys.c | 83 | !Ekernel/sys.c |
84 | !Ekernel/rcupdate.c | 84 | !Ekernel/rcupdate.c |
85 | </sect1> | 85 | </sect1> |
86 | 86 | ||
87 | </chapter> | 87 | </chapter> |
88 | 88 | ||
89 | <chapter id="adt"> | 89 | <chapter id="adt"> |
90 | <title>Data Types</title> | 90 | <title>Data Types</title> |
91 | <sect1><title>Doubly Linked Lists</title> | 91 | <sect1><title>Doubly Linked Lists</title> |
92 | !Iinclude/linux/list.h | 92 | !Iinclude/linux/list.h |
93 | </sect1> | 93 | </sect1> |
94 | </chapter> | 94 | </chapter> |
95 | 95 | ||
96 | <chapter id="libc"> | 96 | <chapter id="libc"> |
97 | <title>Basic C Library Functions</title> | 97 | <title>Basic C Library Functions</title> |
98 | 98 | ||
99 | <para> | 99 | <para> |
100 | When writing drivers, you cannot in general use routines which are | 100 | When writing drivers, you cannot in general use routines which are |
101 | from the C Library. Some of the functions have been found generally | 101 | from the C Library. Some of the functions have been found generally |
102 | useful and they are listed below. The behaviour of these functions | 102 | useful and they are listed below. The behaviour of these functions |
103 | may vary slightly from those defined by ANSI, and these deviations | 103 | may vary slightly from those defined by ANSI, and these deviations |
104 | are noted in the text. | 104 | are noted in the text. |
105 | </para> | 105 | </para> |
106 | 106 | ||
107 | <sect1><title>String Conversions</title> | 107 | <sect1><title>String Conversions</title> |
108 | !Ilib/vsprintf.c | 108 | !Ilib/vsprintf.c |
109 | !Elib/vsprintf.c | 109 | !Elib/vsprintf.c |
110 | </sect1> | 110 | </sect1> |
111 | <sect1><title>String Manipulation</title> | 111 | <sect1><title>String Manipulation</title> |
112 | <!-- All functions are exported at now | 112 | <!-- All functions are exported at now |
113 | X!Ilib/string.c | 113 | X!Ilib/string.c |
114 | --> | 114 | --> |
115 | !Elib/string.c | 115 | !Elib/string.c |
116 | </sect1> | 116 | </sect1> |
117 | <sect1><title>Bit Operations</title> | 117 | <sect1><title>Bit Operations</title> |
118 | !Iinclude/asm-i386/bitops.h | 118 | !Iinclude/asm-i386/bitops.h |
119 | </sect1> | 119 | </sect1> |
120 | </chapter> | 120 | </chapter> |
121 | 121 | ||
122 | <chapter id="kernel-lib"> | 122 | <chapter id="kernel-lib"> |
123 | <title>Basic Kernel Library Functions</title> | 123 | <title>Basic Kernel Library Functions</title> |
124 | 124 | ||
125 | <para> | 125 | <para> |
126 | The Linux kernel provides more basic utility functions. | 126 | The Linux kernel provides more basic utility functions. |
127 | </para> | 127 | </para> |
128 | 128 | ||
129 | <sect1><title>Bitmap Operations</title> | 129 | <sect1><title>Bitmap Operations</title> |
130 | !Elib/bitmap.c | 130 | !Elib/bitmap.c |
131 | !Ilib/bitmap.c | 131 | !Ilib/bitmap.c |
132 | </sect1> | 132 | </sect1> |
133 | 133 | ||
134 | <sect1><title>Command-line Parsing</title> | 134 | <sect1><title>Command-line Parsing</title> |
135 | !Elib/cmdline.c | 135 | !Elib/cmdline.c |
136 | </sect1> | 136 | </sect1> |
137 | 137 | ||
138 | <sect1><title>CRC Functions</title> | 138 | <sect1><title>CRC Functions</title> |
139 | !Elib/crc16.c | 139 | !Elib/crc16.c |
140 | !Elib/crc32.c | 140 | !Elib/crc32.c |
141 | !Elib/crc-ccitt.c | 141 | !Elib/crc-ccitt.c |
142 | </sect1> | 142 | </sect1> |
143 | </chapter> | 143 | </chapter> |
144 | 144 | ||
145 | <chapter id="mm"> | 145 | <chapter id="mm"> |
146 | <title>Memory Management in Linux</title> | 146 | <title>Memory Management in Linux</title> |
147 | <sect1><title>The Slab Cache</title> | 147 | <sect1><title>The Slab Cache</title> |
148 | !Iinclude/linux/slab.h | 148 | !Iinclude/linux/slab.h |
149 | !Emm/slab.c | 149 | !Emm/slab.c |
150 | </sect1> | 150 | </sect1> |
151 | <sect1><title>User Space Memory Access</title> | 151 | <sect1><title>User Space Memory Access</title> |
152 | !Iinclude/asm-i386/uaccess.h | 152 | !Iinclude/asm-i386/uaccess.h |
153 | !Earch/i386/lib/usercopy.c | 153 | !Earch/i386/lib/usercopy.c |
154 | </sect1> | 154 | </sect1> |
155 | <sect1><title>More Memory Management Functions</title> | 155 | <sect1><title>More Memory Management Functions</title> |
156 | !Iinclude/linux/rmap.h | 156 | !Iinclude/linux/rmap.h |
157 | !Emm/readahead.c | 157 | !Emm/readahead.c |
158 | !Emm/filemap.c | 158 | !Emm/filemap.c |
159 | !Emm/memory.c | 159 | !Emm/memory.c |
160 | !Emm/vmalloc.c | 160 | !Emm/vmalloc.c |
161 | !Emm/mempool.c | 161 | !Emm/mempool.c |
162 | !Emm/page-writeback.c | 162 | !Emm/page-writeback.c |
163 | !Emm/truncate.c | 163 | !Emm/truncate.c |
164 | </sect1> | 164 | </sect1> |
165 | </chapter> | 165 | </chapter> |
166 | 166 | ||
167 | 167 | ||
168 | <chapter id="ipc"> | 168 | <chapter id="ipc"> |
169 | <title>Kernel IPC facilities</title> | 169 | <title>Kernel IPC facilities</title> |
170 | 170 | ||
171 | <sect1><title>IPC utilities</title> | 171 | <sect1><title>IPC utilities</title> |
172 | !Iipc/util.c | 172 | !Iipc/util.c |
173 | </sect1> | 173 | </sect1> |
174 | </chapter> | 174 | </chapter> |
175 | 175 | ||
176 | <chapter id="kfifo"> | 176 | <chapter id="kfifo"> |
177 | <title>FIFO Buffer</title> | 177 | <title>FIFO Buffer</title> |
178 | <sect1><title>kfifo interface</title> | 178 | <sect1><title>kfifo interface</title> |
179 | !Iinclude/linux/kfifo.h | 179 | !Iinclude/linux/kfifo.h |
180 | !Ekernel/kfifo.c | 180 | !Ekernel/kfifo.c |
181 | </sect1> | 181 | </sect1> |
182 | </chapter> | 182 | </chapter> |
183 | 183 | ||
184 | <chapter id="vfs"> | 184 | <chapter id="vfs"> |
185 | <title>The Linux VFS</title> | 185 | <title>The Linux VFS</title> |
186 | <sect1><title>The Filesystem types</title> | 186 | <sect1><title>The Filesystem types</title> |
187 | !Iinclude/linux/fs.h | 187 | !Iinclude/linux/fs.h |
188 | </sect1> | 188 | </sect1> |
189 | <sect1><title>The Directory Cache</title> | 189 | <sect1><title>The Directory Cache</title> |
190 | !Efs/dcache.c | 190 | !Efs/dcache.c |
191 | !Iinclude/linux/dcache.h | 191 | !Iinclude/linux/dcache.h |
192 | </sect1> | 192 | </sect1> |
193 | <sect1><title>Inode Handling</title> | 193 | <sect1><title>Inode Handling</title> |
194 | !Efs/inode.c | 194 | !Efs/inode.c |
195 | !Efs/bad_inode.c | 195 | !Efs/bad_inode.c |
196 | </sect1> | 196 | </sect1> |
197 | <sect1><title>Registration and Superblocks</title> | 197 | <sect1><title>Registration and Superblocks</title> |
198 | !Efs/super.c | 198 | !Efs/super.c |
199 | </sect1> | 199 | </sect1> |
200 | <sect1><title>File Locks</title> | 200 | <sect1><title>File Locks</title> |
201 | !Efs/locks.c | 201 | !Efs/locks.c |
202 | !Ifs/locks.c | 202 | !Ifs/locks.c |
203 | </sect1> | 203 | </sect1> |
204 | <sect1><title>Other Functions</title> | 204 | <sect1><title>Other Functions</title> |
205 | !Efs/mpage.c | 205 | !Efs/mpage.c |
206 | !Efs/namei.c | 206 | !Efs/namei.c |
207 | !Efs/buffer.c | 207 | !Efs/buffer.c |
208 | !Efs/bio.c | 208 | !Efs/bio.c |
209 | !Efs/seq_file.c | 209 | !Efs/seq_file.c |
210 | !Efs/filesystems.c | 210 | !Efs/filesystems.c |
211 | !Efs/fs-writeback.c | 211 | !Efs/fs-writeback.c |
212 | !Efs/block_dev.c | 212 | !Efs/block_dev.c |
213 | </sect1> | 213 | </sect1> |
214 | </chapter> | 214 | </chapter> |
215 | 215 | ||
216 | <chapter id="proc"> | 216 | <chapter id="proc"> |
217 | <title>The proc filesystem</title> | 217 | <title>The proc filesystem</title> |
218 | 218 | ||
219 | <sect1><title>sysctl interface</title> | 219 | <sect1><title>sysctl interface</title> |
220 | !Ekernel/sysctl.c | 220 | !Ekernel/sysctl.c |
221 | </sect1> | 221 | </sect1> |
222 | 222 | ||
223 | <sect1><title>proc filesystem interface</title> | 223 | <sect1><title>proc filesystem interface</title> |
224 | !Ifs/proc/base.c | 224 | !Ifs/proc/base.c |
225 | </sect1> | 225 | </sect1> |
226 | </chapter> | 226 | </chapter> |
227 | 227 | ||
228 | <chapter id="sysfs"> | 228 | <chapter id="sysfs"> |
229 | <title>The Filesystem for Exporting Kernel Objects</title> | 229 | <title>The Filesystem for Exporting Kernel Objects</title> |
230 | !Efs/sysfs/file.c | 230 | !Efs/sysfs/file.c |
231 | !Efs/sysfs/symlink.c | 231 | !Efs/sysfs/symlink.c |
232 | !Efs/sysfs/bin.c | 232 | !Efs/sysfs/bin.c |
233 | </chapter> | 233 | </chapter> |
234 | 234 | ||
235 | <chapter id="debugfs"> | 235 | <chapter id="debugfs"> |
236 | <title>The debugfs filesystem</title> | 236 | <title>The debugfs filesystem</title> |
237 | 237 | ||
238 | <sect1><title>debugfs interface</title> | 238 | <sect1><title>debugfs interface</title> |
239 | !Efs/debugfs/inode.c | 239 | !Efs/debugfs/inode.c |
240 | !Efs/debugfs/file.c | 240 | !Efs/debugfs/file.c |
241 | </sect1> | 241 | </sect1> |
242 | </chapter> | 242 | </chapter> |
243 | 243 | ||
244 | <chapter id="relayfs"> | 244 | <chapter id="relayfs"> |
245 | <title>relay interface support</title> | 245 | <title>relay interface support</title> |
246 | 246 | ||
247 | <para> | 247 | <para> |
248 | Relay interface support | 248 | Relay interface support |
249 | is designed to provide an efficient mechanism for tools and | 249 | is designed to provide an efficient mechanism for tools and |
250 | facilities to relay large amounts of data from kernel space to | 250 | facilities to relay large amounts of data from kernel space to |
251 | user space. | 251 | user space. |
252 | </para> | 252 | </para> |
253 | 253 | ||
254 | <sect1><title>relay interface</title> | 254 | <sect1><title>relay interface</title> |
255 | !Ekernel/relay.c | 255 | !Ekernel/relay.c |
256 | !Ikernel/relay.c | 256 | !Ikernel/relay.c |
257 | </sect1> | 257 | </sect1> |
258 | </chapter> | 258 | </chapter> |
259 | 259 | ||
260 | <chapter id="netcore"> | 260 | <chapter id="netcore"> |
261 | <title>Linux Networking</title> | 261 | <title>Linux Networking</title> |
262 | <sect1><title>Networking Base Types</title> | 262 | <sect1><title>Networking Base Types</title> |
263 | !Iinclude/linux/net.h | 263 | !Iinclude/linux/net.h |
264 | </sect1> | 264 | </sect1> |
265 | <sect1><title>Socket Buffer Functions</title> | 265 | <sect1><title>Socket Buffer Functions</title> |
266 | !Iinclude/linux/skbuff.h | 266 | !Iinclude/linux/skbuff.h |
267 | !Iinclude/net/sock.h | 267 | !Iinclude/net/sock.h |
268 | !Enet/socket.c | 268 | !Enet/socket.c |
269 | !Enet/core/skbuff.c | 269 | !Enet/core/skbuff.c |
270 | !Enet/core/sock.c | 270 | !Enet/core/sock.c |
271 | !Enet/core/datagram.c | 271 | !Enet/core/datagram.c |
272 | !Enet/core/stream.c | 272 | !Enet/core/stream.c |
273 | </sect1> | 273 | </sect1> |
274 | <sect1><title>Socket Filter</title> | 274 | <sect1><title>Socket Filter</title> |
275 | !Enet/core/filter.c | 275 | !Enet/core/filter.c |
276 | </sect1> | 276 | </sect1> |
277 | <sect1><title>Generic Network Statistics</title> | 277 | <sect1><title>Generic Network Statistics</title> |
278 | !Iinclude/linux/gen_stats.h | 278 | !Iinclude/linux/gen_stats.h |
279 | !Enet/core/gen_stats.c | 279 | !Enet/core/gen_stats.c |
280 | !Enet/core/gen_estimator.c | 280 | !Enet/core/gen_estimator.c |
281 | </sect1> | 281 | </sect1> |
282 | <sect1><title>SUN RPC subsystem</title> | 282 | <sect1><title>SUN RPC subsystem</title> |
283 | <!-- The !D functionality is not perfect, garbage has to be protected by comments | 283 | <!-- The !D functionality is not perfect, garbage has to be protected by comments |
284 | !Dnet/sunrpc/sunrpc_syms.c | 284 | !Dnet/sunrpc/sunrpc_syms.c |
285 | --> | 285 | --> |
286 | !Enet/sunrpc/xdr.c | 286 | !Enet/sunrpc/xdr.c |
287 | !Enet/sunrpc/svcsock.c | 287 | !Enet/sunrpc/svcsock.c |
288 | !Enet/sunrpc/sched.c | 288 | !Enet/sunrpc/sched.c |
289 | </sect1> | 289 | </sect1> |
290 | </chapter> | 290 | </chapter> |
291 | 291 | ||
292 | <chapter id="netdev"> | 292 | <chapter id="netdev"> |
293 | <title>Network device support</title> | 293 | <title>Network device support</title> |
294 | <sect1><title>Driver Support</title> | 294 | <sect1><title>Driver Support</title> |
295 | !Enet/core/dev.c | 295 | !Enet/core/dev.c |
296 | !Enet/ethernet/eth.c | 296 | !Enet/ethernet/eth.c |
297 | !Iinclude/linux/etherdevice.h | 297 | !Iinclude/linux/etherdevice.h |
298 | <!-- FIXME: Removed for now since no structured comments in source | 298 | <!-- FIXME: Removed for now since no structured comments in source |
299 | X!Enet/core/wireless.c | 299 | X!Enet/core/wireless.c |
300 | --> | 300 | --> |
301 | </sect1> | 301 | </sect1> |
302 | <sect1><title>Synchronous PPP</title> | 302 | <sect1><title>Synchronous PPP</title> |
303 | !Edrivers/net/wan/syncppp.c | 303 | !Edrivers/net/wan/syncppp.c |
304 | </sect1> | 304 | </sect1> |
305 | </chapter> | 305 | </chapter> |
306 | 306 | ||
307 | <chapter id="modload"> | 307 | <chapter id="modload"> |
308 | <title>Module Support</title> | 308 | <title>Module Support</title> |
309 | <sect1><title>Module Loading</title> | 309 | <sect1><title>Module Loading</title> |
310 | !Ekernel/kmod.c | 310 | !Ekernel/kmod.c |
311 | </sect1> | 311 | </sect1> |
312 | <sect1><title>Inter Module support</title> | 312 | <sect1><title>Inter Module support</title> |
313 | <para> | 313 | <para> |
314 | Refer to the file kernel/module.c for more information. | 314 | Refer to the file kernel/module.c for more information. |
315 | </para> | 315 | </para> |
316 | <!-- FIXME: Removed for now since no structured comments in source | 316 | <!-- FIXME: Removed for now since no structured comments in source |
317 | X!Ekernel/module.c | 317 | X!Ekernel/module.c |
318 | --> | 318 | --> |
319 | </sect1> | 319 | </sect1> |
320 | </chapter> | 320 | </chapter> |
321 | 321 | ||
322 | <chapter id="hardware"> | 322 | <chapter id="hardware"> |
323 | <title>Hardware Interfaces</title> | 323 | <title>Hardware Interfaces</title> |
324 | <sect1><title>Interrupt Handling</title> | 324 | <sect1><title>Interrupt Handling</title> |
325 | !Ekernel/irq/manage.c | 325 | !Ekernel/irq/manage.c |
326 | </sect1> | 326 | </sect1> |
327 | 327 | ||
328 | <sect1><title>Resources Management</title> | 328 | <sect1><title>Resources Management</title> |
329 | !Ikernel/resource.c | 329 | !Ikernel/resource.c |
330 | </sect1> | 330 | </sect1> |
331 | 331 | ||
332 | <sect1><title>MTRR Handling</title> | 332 | <sect1><title>MTRR Handling</title> |
333 | !Earch/i386/kernel/cpu/mtrr/main.c | 333 | !Earch/i386/kernel/cpu/mtrr/main.c |
334 | </sect1> | 334 | </sect1> |
335 | 335 | ||
336 | <sect1><title>PCI Support Library</title> | 336 | <sect1><title>PCI Support Library</title> |
337 | !Edrivers/pci/pci.c | 337 | !Edrivers/pci/pci.c |
338 | !Edrivers/pci/pci-driver.c | 338 | !Edrivers/pci/pci-driver.c |
339 | !Edrivers/pci/remove.c | 339 | !Edrivers/pci/remove.c |
340 | !Edrivers/pci/pci-acpi.c | 340 | !Edrivers/pci/pci-acpi.c |
341 | !Edrivers/pci/search.c | 341 | !Edrivers/pci/search.c |
342 | !Edrivers/pci/msi.c | 342 | !Edrivers/pci/msi.c |
343 | !Edrivers/pci/bus.c | 343 | !Edrivers/pci/bus.c |
344 | <!-- FIXME: Removed for now since no structured comments in source | 344 | <!-- FIXME: Removed for now since no structured comments in source |
345 | X!Edrivers/pci/hotplug.c | 345 | X!Edrivers/pci/hotplug.c |
346 | --> | 346 | --> |
347 | !Edrivers/pci/probe.c | 347 | !Edrivers/pci/probe.c |
348 | !Edrivers/pci/rom.c | 348 | !Edrivers/pci/rom.c |
349 | </sect1> | 349 | </sect1> |
350 | <sect1><title>PCI Hotplug Support Library</title> | 350 | <sect1><title>PCI Hotplug Support Library</title> |
351 | !Edrivers/pci/hotplug/pci_hotplug_core.c | 351 | !Edrivers/pci/hotplug/pci_hotplug_core.c |
352 | </sect1> | 352 | </sect1> |
353 | <sect1><title>MCA Architecture</title> | 353 | <sect1><title>MCA Architecture</title> |
354 | <sect2><title>MCA Device Functions</title> | 354 | <sect2><title>MCA Device Functions</title> |
355 | <para> | 355 | <para> |
356 | Refer to the file arch/i386/kernel/mca.c for more information. | 356 | Refer to the file arch/i386/kernel/mca.c for more information. |
357 | </para> | 357 | </para> |
358 | <!-- FIXME: Removed for now since no structured comments in source | 358 | <!-- FIXME: Removed for now since no structured comments in source |
359 | X!Earch/i386/kernel/mca.c | 359 | X!Earch/i386/kernel/mca.c |
360 | --> | 360 | --> |
361 | </sect2> | 361 | </sect2> |
362 | <sect2><title>MCA Bus DMA</title> | 362 | <sect2><title>MCA Bus DMA</title> |
363 | !Iinclude/asm-i386/mca_dma.h | 363 | !Iinclude/asm-i386/mca_dma.h |
364 | </sect2> | 364 | </sect2> |
365 | </sect1> | 365 | </sect1> |
366 | </chapter> | 366 | </chapter> |
367 | 367 | ||
368 | <chapter id="firmware"> | 368 | <chapter id="firmware"> |
369 | <title>Firmware Interfaces</title> | 369 | <title>Firmware Interfaces</title> |
370 | <sect1><title>DMI Interfaces</title> | 370 | <sect1><title>DMI Interfaces</title> |
371 | !Edrivers/firmware/dmi_scan.c | 371 | !Edrivers/firmware/dmi_scan.c |
372 | </sect1> | 372 | </sect1> |
373 | </chapter> | 373 | </chapter> |
374 | 374 | ||
375 | <chapter id="security"> | 375 | <chapter id="security"> |
376 | <title>Security Framework</title> | 376 | <title>Security Framework</title> |
377 | !Esecurity/security.c | 377 | !Esecurity/security.c |
378 | </chapter> | 378 | </chapter> |
379 | 379 | ||
380 | <chapter id="audit"> | 380 | <chapter id="audit"> |
381 | <title>Audit Interfaces</title> | 381 | <title>Audit Interfaces</title> |
382 | !Ekernel/audit.c | 382 | !Ekernel/audit.c |
383 | !Ikernel/auditsc.c | 383 | !Ikernel/auditsc.c |
384 | !Ikernel/auditfilter.c | 384 | !Ikernel/auditfilter.c |
385 | </chapter> | 385 | </chapter> |
386 | 386 | ||
387 | <chapter id="accounting"> | 387 | <chapter id="accounting"> |
388 | <title>Accounting Framework</title> | 388 | <title>Accounting Framework</title> |
389 | !Ikernel/acct.c | 389 | !Ikernel/acct.c |
390 | </chapter> | 390 | </chapter> |
391 | 391 | ||
392 | <chapter id="pmfuncs"> | 392 | <chapter id="pmfuncs"> |
393 | <title>Power Management</title> | 393 | <title>Power Management</title> |
394 | !Ekernel/power/pm.c | 394 | !Ekernel/power/pm.c |
395 | </chapter> | 395 | </chapter> |
396 | 396 | ||
397 | <chapter id="devdrivers"> | 397 | <chapter id="devdrivers"> |
398 | <title>Device drivers infrastructure</title> | 398 | <title>Device drivers infrastructure</title> |
399 | <sect1><title>Device Drivers Base</title> | 399 | <sect1><title>Device Drivers Base</title> |
400 | <!-- | 400 | <!-- |
401 | X!Iinclude/linux/device.h | 401 | X!Iinclude/linux/device.h |
402 | --> | 402 | --> |
403 | !Edrivers/base/driver.c | 403 | !Edrivers/base/driver.c |
404 | !Edrivers/base/core.c | 404 | !Edrivers/base/core.c |
405 | !Edrivers/base/class.c | 405 | !Edrivers/base/class.c |
406 | !Edrivers/base/firmware_class.c | 406 | !Edrivers/base/firmware_class.c |
407 | !Edrivers/base/transport_class.c | 407 | !Edrivers/base/transport_class.c |
408 | !Edrivers/base/dmapool.c | 408 | !Edrivers/base/dmapool.c |
409 | <!-- Cannot be included, because | 409 | <!-- Cannot be included, because |
410 | attribute_container_add_class_device_adapter | 410 | attribute_container_add_class_device_adapter |
411 | and attribute_container_classdev_to_container | 411 | and attribute_container_classdev_to_container |
412 | exceed allowed 44 characters maximum | 412 | exceed allowed 44 characters maximum |
413 | X!Edrivers/base/attribute_container.c | 413 | X!Edrivers/base/attribute_container.c |
414 | --> | 414 | --> |
415 | !Edrivers/base/sys.c | 415 | !Edrivers/base/sys.c |
416 | <!-- | 416 | <!-- |
417 | X!Edrivers/base/interface.c | 417 | X!Edrivers/base/interface.c |
418 | --> | 418 | --> |
419 | !Edrivers/base/platform.c | 419 | !Edrivers/base/platform.c |
420 | !Edrivers/base/bus.c | 420 | !Edrivers/base/bus.c |
421 | </sect1> | 421 | </sect1> |
422 | <sect1><title>Device Drivers Power Management</title> | 422 | <sect1><title>Device Drivers Power Management</title> |
423 | !Edrivers/base/power/main.c | 423 | !Edrivers/base/power/main.c |
424 | !Edrivers/base/power/resume.c | 424 | !Edrivers/base/power/resume.c |
425 | !Edrivers/base/power/suspend.c | 425 | !Edrivers/base/power/suspend.c |
426 | </sect1> | 426 | </sect1> |
427 | <sect1><title>Device Drivers ACPI Support</title> | 427 | <sect1><title>Device Drivers ACPI Support</title> |
428 | <!-- Internal functions only | 428 | <!-- Internal functions only |
429 | X!Edrivers/acpi/sleep/main.c | 429 | X!Edrivers/acpi/sleep/main.c |
430 | X!Edrivers/acpi/sleep/wakeup.c | 430 | X!Edrivers/acpi/sleep/wakeup.c |
431 | X!Edrivers/acpi/motherboard.c | 431 | X!Edrivers/acpi/motherboard.c |
432 | X!Edrivers/acpi/bus.c | 432 | X!Edrivers/acpi/bus.c |
433 | --> | 433 | --> |
434 | !Edrivers/acpi/scan.c | 434 | !Edrivers/acpi/scan.c |
435 | !Idrivers/acpi/scan.c | 435 | !Idrivers/acpi/scan.c |
436 | <!-- No correct structured comments | 436 | <!-- No correct structured comments |
437 | X!Edrivers/acpi/pci_bind.c | 437 | X!Edrivers/acpi/pci_bind.c |
438 | --> | 438 | --> |
439 | </sect1> | 439 | </sect1> |
440 | <sect1><title>Device drivers PnP support</title> | 440 | <sect1><title>Device drivers PnP support</title> |
441 | !Edrivers/pnp/core.c | 441 | !Edrivers/pnp/core.c |
442 | <!-- No correct structured comments | 442 | <!-- No correct structured comments |
443 | X!Edrivers/pnp/system.c | 443 | X!Edrivers/pnp/system.c |
444 | --> | 444 | --> |
445 | !Edrivers/pnp/card.c | 445 | !Edrivers/pnp/card.c |
446 | !Edrivers/pnp/driver.c | 446 | !Edrivers/pnp/driver.c |
447 | !Edrivers/pnp/manager.c | 447 | !Edrivers/pnp/manager.c |
448 | !Edrivers/pnp/support.c | 448 | !Edrivers/pnp/support.c |
449 | </sect1> | 449 | </sect1> |
450 | </chapter> | 450 | </chapter> |
451 | 451 | ||
452 | <chapter id="blkdev"> | 452 | <chapter id="blkdev"> |
453 | <title>Block Devices</title> | 453 | <title>Block Devices</title> |
454 | !Eblock/ll_rw_blk.c | 454 | !Eblock/ll_rw_blk.c |
455 | </chapter> | 455 | </chapter> |
456 | 456 | ||
457 | <chapter id="chrdev"> | ||
458 | <title>Char devices</title> | ||
459 | !Efs/char_dev.c | ||
460 | </chapter> | ||
461 | |||
457 | <chapter id="miscdev"> | 462 | <chapter id="miscdev"> |
458 | <title>Miscellaneous Devices</title> | 463 | <title>Miscellaneous Devices</title> |
459 | !Edrivers/char/misc.c | 464 | !Edrivers/char/misc.c |
460 | </chapter> | 465 | </chapter> |
461 | 466 | ||
462 | <chapter id="parportdev"> | 467 | <chapter id="parportdev"> |
463 | <title>Parallel Port Devices</title> | 468 | <title>Parallel Port Devices</title> |
464 | !Iinclude/linux/parport.h | 469 | !Iinclude/linux/parport.h |
465 | !Edrivers/parport/ieee1284.c | 470 | !Edrivers/parport/ieee1284.c |
466 | !Edrivers/parport/share.c | 471 | !Edrivers/parport/share.c |
467 | !Idrivers/parport/daisy.c | 472 | !Idrivers/parport/daisy.c |
468 | </chapter> | 473 | </chapter> |
469 | 474 | ||
470 | <chapter id="viddev"> | 475 | <chapter id="viddev"> |
471 | <title>Video4Linux</title> | 476 | <title>Video4Linux</title> |
472 | !Edrivers/media/video/videodev.c | 477 | !Edrivers/media/video/videodev.c |
473 | </chapter> | 478 | </chapter> |
474 | 479 | ||
475 | <chapter id="snddev"> | 480 | <chapter id="snddev"> |
476 | <title>Sound Devices</title> | 481 | <title>Sound Devices</title> |
477 | !Iinclude/sound/core.h | 482 | !Iinclude/sound/core.h |
478 | !Esound/sound_core.c | 483 | !Esound/sound_core.c |
479 | !Iinclude/sound/pcm.h | 484 | !Iinclude/sound/pcm.h |
480 | !Esound/core/pcm.c | 485 | !Esound/core/pcm.c |
481 | !Esound/core/device.c | 486 | !Esound/core/device.c |
482 | !Esound/core/info.c | 487 | !Esound/core/info.c |
483 | !Esound/core/rawmidi.c | 488 | !Esound/core/rawmidi.c |
484 | !Esound/core/sound.c | 489 | !Esound/core/sound.c |
485 | !Esound/core/memory.c | 490 | !Esound/core/memory.c |
486 | !Esound/core/pcm_memory.c | 491 | !Esound/core/pcm_memory.c |
487 | !Esound/core/init.c | 492 | !Esound/core/init.c |
488 | !Esound/core/isadma.c | 493 | !Esound/core/isadma.c |
489 | !Esound/core/control.c | 494 | !Esound/core/control.c |
490 | !Esound/core/pcm_lib.c | 495 | !Esound/core/pcm_lib.c |
491 | !Esound/core/hwdep.c | 496 | !Esound/core/hwdep.c |
492 | !Esound/core/pcm_native.c | 497 | !Esound/core/pcm_native.c |
493 | !Esound/core/memalloc.c | 498 | !Esound/core/memalloc.c |
494 | <!-- FIXME: Removed for now since no structured comments in source | 499 | <!-- FIXME: Removed for now since no structured comments in source |
495 | X!Isound/sound_firmware.c | 500 | X!Isound/sound_firmware.c |
496 | --> | 501 | --> |
497 | </chapter> | 502 | </chapter> |
498 | 503 | ||
499 | <chapter id="uart16x50"> | 504 | <chapter id="uart16x50"> |
500 | <title>16x50 UART Driver</title> | 505 | <title>16x50 UART Driver</title> |
501 | !Iinclude/linux/serial_core.h | 506 | !Iinclude/linux/serial_core.h |
502 | !Edrivers/serial/serial_core.c | 507 | !Edrivers/serial/serial_core.c |
503 | !Edrivers/serial/8250.c | 508 | !Edrivers/serial/8250.c |
504 | </chapter> | 509 | </chapter> |
505 | 510 | ||
506 | <chapter id="z85230"> | 511 | <chapter id="z85230"> |
507 | <title>Z85230 Support Library</title> | 512 | <title>Z85230 Support Library</title> |
508 | !Edrivers/net/wan/z85230.c | 513 | !Edrivers/net/wan/z85230.c |
509 | </chapter> | 514 | </chapter> |
510 | 515 | ||
511 | <chapter id="fbdev"> | 516 | <chapter id="fbdev"> |
512 | <title>Frame Buffer Library</title> | 517 | <title>Frame Buffer Library</title> |
513 | 518 | ||
514 | <para> | 519 | <para> |
515 | The frame buffer drivers depend heavily on four data structures. | 520 | The frame buffer drivers depend heavily on four data structures. |
516 | These structures are declared in include/linux/fb.h. They are | 521 | These structures are declared in include/linux/fb.h. They are |
517 | fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs. | 522 | fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs. |
518 | The last three can be made available to and from userland. | 523 | The last three can be made available to and from userland. |
519 | </para> | 524 | </para> |
520 | 525 | ||
521 | <para> | 526 | <para> |
522 | fb_info defines the current state of a particular video card. | 527 | fb_info defines the current state of a particular video card. |
523 | Inside fb_info, there exists a fb_ops structure which is a | 528 | Inside fb_info, there exists a fb_ops structure which is a |
524 | collection of needed functions to make fbdev and fbcon work. | 529 | collection of needed functions to make fbdev and fbcon work. |
525 | fb_info is only visible to the kernel. | 530 | fb_info is only visible to the kernel. |
526 | </para> | 531 | </para> |
527 | 532 | ||
528 | <para> | 533 | <para> |
529 | fb_var_screeninfo is used to describe the features of a video card | 534 | fb_var_screeninfo is used to describe the features of a video card |
530 | that are user defined. With fb_var_screeninfo, things such as | 535 | that are user defined. With fb_var_screeninfo, things such as |
531 | depth and the resolution may be defined. | 536 | depth and the resolution may be defined. |
532 | </para> | 537 | </para> |
533 | 538 | ||
534 | <para> | 539 | <para> |
535 | The next structure is fb_fix_screeninfo. This defines the | 540 | The next structure is fb_fix_screeninfo. This defines the |
536 | properties of a card that are created when a mode is set and can't | 541 | properties of a card that are created when a mode is set and can't |
537 | be changed otherwise. A good example of this is the start of the | 542 | be changed otherwise. A good example of this is the start of the |
538 | frame buffer memory. This "locks" the address of the frame buffer | 543 | frame buffer memory. This "locks" the address of the frame buffer |
539 | memory, so that it cannot be changed or moved. | 544 | memory, so that it cannot be changed or moved. |
540 | </para> | 545 | </para> |
541 | 546 | ||
542 | <para> | 547 | <para> |
543 | The last structure is fb_monospecs. In the old API, there was | 548 | The last structure is fb_monospecs. In the old API, there was |
544 | little importance for fb_monospecs. This allowed for forbidden things | 549 | little importance for fb_monospecs. This allowed for forbidden things |
545 | such as setting a mode of 800x600 on a fix frequency monitor. With | 550 | such as setting a mode of 800x600 on a fix frequency monitor. With |
546 | the new API, fb_monospecs prevents such things, and if used | 551 | the new API, fb_monospecs prevents such things, and if used |
547 | correctly, can prevent a monitor from being cooked. fb_monospecs | 552 | correctly, can prevent a monitor from being cooked. fb_monospecs |
548 | will not be useful until kernels 2.5.x. | 553 | will not be useful until kernels 2.5.x. |
549 | </para> | 554 | </para> |
550 | 555 | ||
551 | <sect1><title>Frame Buffer Memory</title> | 556 | <sect1><title>Frame Buffer Memory</title> |
552 | !Edrivers/video/fbmem.c | 557 | !Edrivers/video/fbmem.c |
553 | </sect1> | 558 | </sect1> |
554 | <!-- | 559 | <!-- |
555 | <sect1><title>Frame Buffer Console</title> | 560 | <sect1><title>Frame Buffer Console</title> |
556 | X!Edrivers/video/console/fbcon.c | 561 | X!Edrivers/video/console/fbcon.c |
557 | </sect1> | 562 | </sect1> |
558 | --> | 563 | --> |
559 | <sect1><title>Frame Buffer Colormap</title> | 564 | <sect1><title>Frame Buffer Colormap</title> |
560 | !Edrivers/video/fbcmap.c | 565 | !Edrivers/video/fbcmap.c |
561 | </sect1> | 566 | </sect1> |
562 | <!-- FIXME: | 567 | <!-- FIXME: |
563 | drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment | 568 | drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment |
564 | out until somebody adds docs. KAO | 569 | out until somebody adds docs. KAO |
565 | <sect1><title>Frame Buffer Generic Functions</title> | 570 | <sect1><title>Frame Buffer Generic Functions</title> |
566 | X!Idrivers/video/fbgen.c | 571 | X!Idrivers/video/fbgen.c |
567 | </sect1> | 572 | </sect1> |
568 | KAO --> | 573 | KAO --> |
569 | <sect1><title>Frame Buffer Video Mode Database</title> | 574 | <sect1><title>Frame Buffer Video Mode Database</title> |
570 | !Idrivers/video/modedb.c | 575 | !Idrivers/video/modedb.c |
571 | !Edrivers/video/modedb.c | 576 | !Edrivers/video/modedb.c |
572 | </sect1> | 577 | </sect1> |
573 | <sect1><title>Frame Buffer Macintosh Video Mode Database</title> | 578 | <sect1><title>Frame Buffer Macintosh Video Mode Database</title> |
574 | !Edrivers/video/macmodes.c | 579 | !Edrivers/video/macmodes.c |
575 | </sect1> | 580 | </sect1> |
576 | <sect1><title>Frame Buffer Fonts</title> | 581 | <sect1><title>Frame Buffer Fonts</title> |
577 | <para> | 582 | <para> |
578 | Refer to the file drivers/video/console/fonts.c for more information. | 583 | Refer to the file drivers/video/console/fonts.c for more information. |
579 | </para> | 584 | </para> |
580 | <!-- FIXME: Removed for now since no structured comments in source | 585 | <!-- FIXME: Removed for now since no structured comments in source |
581 | X!Idrivers/video/console/fonts.c | 586 | X!Idrivers/video/console/fonts.c |
582 | --> | 587 | --> |
583 | </sect1> | 588 | </sect1> |
584 | </chapter> | 589 | </chapter> |
585 | </book> | 590 | </book> |
586 | 591 |
fs/char_dev.c
1 | /* | 1 | /* |
2 | * linux/fs/char_dev.c | 2 | * linux/fs/char_dev.c |
3 | * | 3 | * |
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 4 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | 11 | ||
12 | #include <linux/major.h> | 12 | #include <linux/major.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/smp_lock.h> | 15 | #include <linux/smp_lock.h> |
16 | #include <linux/seq_file.h> | 16 | #include <linux/seq_file.h> |
17 | 17 | ||
18 | #include <linux/kobject.h> | 18 | #include <linux/kobject.h> |
19 | #include <linux/kobj_map.h> | 19 | #include <linux/kobj_map.h> |
20 | #include <linux/cdev.h> | 20 | #include <linux/cdev.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/backing-dev.h> | 22 | #include <linux/backing-dev.h> |
23 | 23 | ||
24 | #ifdef CONFIG_KMOD | 24 | #ifdef CONFIG_KMOD |
25 | #include <linux/kmod.h> | 25 | #include <linux/kmod.h> |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * capabilities for /dev/mem, /dev/kmem and similar directly mappable character | 29 | * capabilities for /dev/mem, /dev/kmem and similar directly mappable character |
30 | * devices | 30 | * devices |
31 | * - permits shared-mmap for read, write and/or exec | 31 | * - permits shared-mmap for read, write and/or exec |
32 | * - does not permit private mmap in NOMMU mode (can't do COW) | 32 | * - does not permit private mmap in NOMMU mode (can't do COW) |
33 | * - no readahead or I/O queue unplugging required | 33 | * - no readahead or I/O queue unplugging required |
34 | */ | 34 | */ |
35 | struct backing_dev_info directly_mappable_cdev_bdi = { | 35 | struct backing_dev_info directly_mappable_cdev_bdi = { |
36 | .capabilities = ( | 36 | .capabilities = ( |
37 | #ifdef CONFIG_MMU | 37 | #ifdef CONFIG_MMU |
38 | /* permit private copies of the data to be taken */ | 38 | /* permit private copies of the data to be taken */ |
39 | BDI_CAP_MAP_COPY | | 39 | BDI_CAP_MAP_COPY | |
40 | #endif | 40 | #endif |
41 | /* permit direct mmap, for read, write or exec */ | 41 | /* permit direct mmap, for read, write or exec */ |
42 | BDI_CAP_MAP_DIRECT | | 42 | BDI_CAP_MAP_DIRECT | |
43 | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP), | 43 | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP), |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static struct kobj_map *cdev_map; | 46 | static struct kobj_map *cdev_map; |
47 | 47 | ||
48 | static DEFINE_MUTEX(chrdevs_lock); | 48 | static DEFINE_MUTEX(chrdevs_lock); |
49 | 49 | ||
50 | static struct char_device_struct { | 50 | static struct char_device_struct { |
51 | struct char_device_struct *next; | 51 | struct char_device_struct *next; |
52 | unsigned int major; | 52 | unsigned int major; |
53 | unsigned int baseminor; | 53 | unsigned int baseminor; |
54 | int minorct; | 54 | int minorct; |
55 | char name[64]; | 55 | char name[64]; |
56 | struct file_operations *fops; | 56 | struct file_operations *fops; |
57 | struct cdev *cdev; /* will die */ | 57 | struct cdev *cdev; /* will die */ |
58 | } *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; | 58 | } *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; |
59 | 59 | ||
60 | /* index in the above */ | 60 | /* index in the above */ |
61 | static inline int major_to_index(int major) | 61 | static inline int major_to_index(int major) |
62 | { | 62 | { |
63 | return major % CHRDEV_MAJOR_HASH_SIZE; | 63 | return major % CHRDEV_MAJOR_HASH_SIZE; |
64 | } | 64 | } |
65 | 65 | ||
66 | #ifdef CONFIG_PROC_FS | 66 | #ifdef CONFIG_PROC_FS |
67 | 67 | ||
68 | void chrdev_show(struct seq_file *f, off_t offset) | 68 | void chrdev_show(struct seq_file *f, off_t offset) |
69 | { | 69 | { |
70 | struct char_device_struct *cd; | 70 | struct char_device_struct *cd; |
71 | 71 | ||
72 | if (offset < CHRDEV_MAJOR_HASH_SIZE) { | 72 | if (offset < CHRDEV_MAJOR_HASH_SIZE) { |
73 | mutex_lock(&chrdevs_lock); | 73 | mutex_lock(&chrdevs_lock); |
74 | for (cd = chrdevs[offset]; cd; cd = cd->next) | 74 | for (cd = chrdevs[offset]; cd; cd = cd->next) |
75 | seq_printf(f, "%3d %s\n", cd->major, cd->name); | 75 | seq_printf(f, "%3d %s\n", cd->major, cd->name); |
76 | mutex_unlock(&chrdevs_lock); | 76 | mutex_unlock(&chrdevs_lock); |
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | #endif /* CONFIG_PROC_FS */ | 80 | #endif /* CONFIG_PROC_FS */ |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * Register a single major with a specified minor range. | 83 | * Register a single major with a specified minor range. |
84 | * | 84 | * |
85 | * If major == 0 this functions will dynamically allocate a major and return | 85 | * If major == 0 this functions will dynamically allocate a major and return |
86 | * its number. | 86 | * its number. |
87 | * | 87 | * |
88 | * If major > 0 this function will attempt to reserve the passed range of | 88 | * If major > 0 this function will attempt to reserve the passed range of |
89 | * minors and will return zero on success. | 89 | * minors and will return zero on success. |
90 | * | 90 | * |
91 | * Returns a -ve errno on failure. | 91 | * Returns a -ve errno on failure. |
92 | */ | 92 | */ |
93 | static struct char_device_struct * | 93 | static struct char_device_struct * |
94 | __register_chrdev_region(unsigned int major, unsigned int baseminor, | 94 | __register_chrdev_region(unsigned int major, unsigned int baseminor, |
95 | int minorct, const char *name) | 95 | int minorct, const char *name) |
96 | { | 96 | { |
97 | struct char_device_struct *cd, **cp; | 97 | struct char_device_struct *cd, **cp; |
98 | int ret = 0; | 98 | int ret = 0; |
99 | int i; | 99 | int i; |
100 | 100 | ||
101 | cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL); | 101 | cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL); |
102 | if (cd == NULL) | 102 | if (cd == NULL) |
103 | return ERR_PTR(-ENOMEM); | 103 | return ERR_PTR(-ENOMEM); |
104 | 104 | ||
105 | mutex_lock(&chrdevs_lock); | 105 | mutex_lock(&chrdevs_lock); |
106 | 106 | ||
107 | /* temporary */ | 107 | /* temporary */ |
108 | if (major == 0) { | 108 | if (major == 0) { |
109 | for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { | 109 | for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { |
110 | if (chrdevs[i] == NULL) | 110 | if (chrdevs[i] == NULL) |
111 | break; | 111 | break; |
112 | } | 112 | } |
113 | 113 | ||
114 | if (i == 0) { | 114 | if (i == 0) { |
115 | ret = -EBUSY; | 115 | ret = -EBUSY; |
116 | goto out; | 116 | goto out; |
117 | } | 117 | } |
118 | major = i; | 118 | major = i; |
119 | ret = major; | 119 | ret = major; |
120 | } | 120 | } |
121 | 121 | ||
122 | cd->major = major; | 122 | cd->major = major; |
123 | cd->baseminor = baseminor; | 123 | cd->baseminor = baseminor; |
124 | cd->minorct = minorct; | 124 | cd->minorct = minorct; |
125 | strncpy(cd->name,name, 64); | 125 | strncpy(cd->name,name, 64); |
126 | 126 | ||
127 | i = major_to_index(major); | 127 | i = major_to_index(major); |
128 | 128 | ||
129 | for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) | 129 | for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) |
130 | if ((*cp)->major > major || | 130 | if ((*cp)->major > major || |
131 | ((*cp)->major == major && | 131 | ((*cp)->major == major && |
132 | (((*cp)->baseminor >= baseminor) || | 132 | (((*cp)->baseminor >= baseminor) || |
133 | ((*cp)->baseminor + (*cp)->minorct > baseminor)))) | 133 | ((*cp)->baseminor + (*cp)->minorct > baseminor)))) |
134 | break; | 134 | break; |
135 | 135 | ||
136 | /* Check for overlapping minor ranges. */ | 136 | /* Check for overlapping minor ranges. */ |
137 | if (*cp && (*cp)->major == major) { | 137 | if (*cp && (*cp)->major == major) { |
138 | int old_min = (*cp)->baseminor; | 138 | int old_min = (*cp)->baseminor; |
139 | int old_max = (*cp)->baseminor + (*cp)->minorct - 1; | 139 | int old_max = (*cp)->baseminor + (*cp)->minorct - 1; |
140 | int new_min = baseminor; | 140 | int new_min = baseminor; |
141 | int new_max = baseminor + minorct - 1; | 141 | int new_max = baseminor + minorct - 1; |
142 | 142 | ||
143 | /* New driver overlaps from the left. */ | 143 | /* New driver overlaps from the left. */ |
144 | if (new_max >= old_min && new_max <= old_max) { | 144 | if (new_max >= old_min && new_max <= old_max) { |
145 | ret = -EBUSY; | 145 | ret = -EBUSY; |
146 | goto out; | 146 | goto out; |
147 | } | 147 | } |
148 | 148 | ||
149 | /* New driver overlaps from the right. */ | 149 | /* New driver overlaps from the right. */ |
150 | if (new_min <= old_max && new_min >= old_min) { | 150 | if (new_min <= old_max && new_min >= old_min) { |
151 | ret = -EBUSY; | 151 | ret = -EBUSY; |
152 | goto out; | 152 | goto out; |
153 | } | 153 | } |
154 | } | 154 | } |
155 | 155 | ||
156 | cd->next = *cp; | 156 | cd->next = *cp; |
157 | *cp = cd; | 157 | *cp = cd; |
158 | mutex_unlock(&chrdevs_lock); | 158 | mutex_unlock(&chrdevs_lock); |
159 | return cd; | 159 | return cd; |
160 | out: | 160 | out: |
161 | mutex_unlock(&chrdevs_lock); | 161 | mutex_unlock(&chrdevs_lock); |
162 | kfree(cd); | 162 | kfree(cd); |
163 | return ERR_PTR(ret); | 163 | return ERR_PTR(ret); |
164 | } | 164 | } |
165 | 165 | ||
166 | static struct char_device_struct * | 166 | static struct char_device_struct * |
167 | __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) | 167 | __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) |
168 | { | 168 | { |
169 | struct char_device_struct *cd = NULL, **cp; | 169 | struct char_device_struct *cd = NULL, **cp; |
170 | int i = major_to_index(major); | 170 | int i = major_to_index(major); |
171 | 171 | ||
172 | mutex_lock(&chrdevs_lock); | 172 | mutex_lock(&chrdevs_lock); |
173 | for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) | 173 | for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) |
174 | if ((*cp)->major == major && | 174 | if ((*cp)->major == major && |
175 | (*cp)->baseminor == baseminor && | 175 | (*cp)->baseminor == baseminor && |
176 | (*cp)->minorct == minorct) | 176 | (*cp)->minorct == minorct) |
177 | break; | 177 | break; |
178 | if (*cp) { | 178 | if (*cp) { |
179 | cd = *cp; | 179 | cd = *cp; |
180 | *cp = cd->next; | 180 | *cp = cd->next; |
181 | } | 181 | } |
182 | mutex_unlock(&chrdevs_lock); | 182 | mutex_unlock(&chrdevs_lock); |
183 | return cd; | 183 | return cd; |
184 | } | 184 | } |
185 | 185 | ||
186 | /** | ||
187 | * register_chrdev_region() - register a range of device numbers | ||
188 | * @from: the first in the desired range of device numbers; must include | ||
189 | * the major number. | ||
190 | * @count: the number of consecutive device numbers required | ||
191 | * @name: the name of the device or driver. | ||
192 | * | ||
193 | * Return value is zero on success, a negative error code on failure. | ||
194 | */ | ||
186 | int register_chrdev_region(dev_t from, unsigned count, const char *name) | 195 | int register_chrdev_region(dev_t from, unsigned count, const char *name) |
187 | { | 196 | { |
188 | struct char_device_struct *cd; | 197 | struct char_device_struct *cd; |
189 | dev_t to = from + count; | 198 | dev_t to = from + count; |
190 | dev_t n, next; | 199 | dev_t n, next; |
191 | 200 | ||
192 | for (n = from; n < to; n = next) { | 201 | for (n = from; n < to; n = next) { |
193 | next = MKDEV(MAJOR(n)+1, 0); | 202 | next = MKDEV(MAJOR(n)+1, 0); |
194 | if (next > to) | 203 | if (next > to) |
195 | next = to; | 204 | next = to; |
196 | cd = __register_chrdev_region(MAJOR(n), MINOR(n), | 205 | cd = __register_chrdev_region(MAJOR(n), MINOR(n), |
197 | next - n, name); | 206 | next - n, name); |
198 | if (IS_ERR(cd)) | 207 | if (IS_ERR(cd)) |
199 | goto fail; | 208 | goto fail; |
200 | } | 209 | } |
201 | return 0; | 210 | return 0; |
202 | fail: | 211 | fail: |
203 | to = n; | 212 | to = n; |
204 | for (n = from; n < to; n = next) { | 213 | for (n = from; n < to; n = next) { |
205 | next = MKDEV(MAJOR(n)+1, 0); | 214 | next = MKDEV(MAJOR(n)+1, 0); |
206 | kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n)); | 215 | kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n)); |
207 | } | 216 | } |
208 | return PTR_ERR(cd); | 217 | return PTR_ERR(cd); |
209 | } | 218 | } |
210 | 219 | ||
220 | /** | ||
221 | * alloc_chrdev_region() - register a range of char device numbers | ||
222 | * @dev: output parameter for first assigned number | ||
223 | * @baseminor: first of the requested range of minor numbers | ||
224 | * @count: the number of minor numbers required | ||
225 | * @name: the name of the associated device or driver | ||
226 | * | ||
227 | * Allocates a range of char device numbers. The major number will be | ||
228 | * chosen dynamically, and returned (along with the first minor number) | ||
229 | * in @dev. Returns zero or a negative error code. | ||
230 | */ | ||
211 | int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | 231 | int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, |
212 | const char *name) | 232 | const char *name) |
213 | { | 233 | { |
214 | struct char_device_struct *cd; | 234 | struct char_device_struct *cd; |
215 | cd = __register_chrdev_region(0, baseminor, count, name); | 235 | cd = __register_chrdev_region(0, baseminor, count, name); |
216 | if (IS_ERR(cd)) | 236 | if (IS_ERR(cd)) |
217 | return PTR_ERR(cd); | 237 | return PTR_ERR(cd); |
218 | *dev = MKDEV(cd->major, cd->baseminor); | 238 | *dev = MKDEV(cd->major, cd->baseminor); |
219 | return 0; | 239 | return 0; |
220 | } | 240 | } |
221 | 241 | ||
222 | /** | 242 | /** |
223 | * register_chrdev() - Register a major number for character devices. | 243 | * register_chrdev() - Register a major number for character devices. |
224 | * @major: major device number or 0 for dynamic allocation | 244 | * @major: major device number or 0 for dynamic allocation |
225 | * @name: name of this range of devices | 245 | * @name: name of this range of devices |
226 | * @fops: file operations associated with this devices | 246 | * @fops: file operations associated with this devices |
227 | * | 247 | * |
228 | * If @major == 0 this functions will dynamically allocate a major and return | 248 | * If @major == 0 this functions will dynamically allocate a major and return |
229 | * its number. | 249 | * its number. |
230 | * | 250 | * |
231 | * If @major > 0 this function will attempt to reserve a device with the given | 251 | * If @major > 0 this function will attempt to reserve a device with the given |
232 | * major number and will return zero on success. | 252 | * major number and will return zero on success. |
233 | * | 253 | * |
234 | * Returns a -ve errno on failure. | 254 | * Returns a -ve errno on failure. |
235 | * | 255 | * |
236 | * The name of this device has nothing to do with the name of the device in | 256 | * The name of this device has nothing to do with the name of the device in |
237 | * /dev. It only helps to keep track of the different owners of devices. If | 257 | * /dev. It only helps to keep track of the different owners of devices. If |
238 | * your module name has only one type of devices it's ok to use e.g. the name | 258 | * your module name has only one type of devices it's ok to use e.g. the name |
239 | * of the module here. | 259 | * of the module here. |
240 | * | 260 | * |
241 | * This function registers a range of 256 minor numbers. The first minor number | 261 | * This function registers a range of 256 minor numbers. The first minor number |
242 | * is 0. | 262 | * is 0. |
243 | */ | 263 | */ |
244 | int register_chrdev(unsigned int major, const char *name, | 264 | int register_chrdev(unsigned int major, const char *name, |
245 | const struct file_operations *fops) | 265 | const struct file_operations *fops) |
246 | { | 266 | { |
247 | struct char_device_struct *cd; | 267 | struct char_device_struct *cd; |
248 | struct cdev *cdev; | 268 | struct cdev *cdev; |
249 | char *s; | 269 | char *s; |
250 | int err = -ENOMEM; | 270 | int err = -ENOMEM; |
251 | 271 | ||
252 | cd = __register_chrdev_region(major, 0, 256, name); | 272 | cd = __register_chrdev_region(major, 0, 256, name); |
253 | if (IS_ERR(cd)) | 273 | if (IS_ERR(cd)) |
254 | return PTR_ERR(cd); | 274 | return PTR_ERR(cd); |
255 | 275 | ||
256 | cdev = cdev_alloc(); | 276 | cdev = cdev_alloc(); |
257 | if (!cdev) | 277 | if (!cdev) |
258 | goto out2; | 278 | goto out2; |
259 | 279 | ||
260 | cdev->owner = fops->owner; | 280 | cdev->owner = fops->owner; |
261 | cdev->ops = fops; | 281 | cdev->ops = fops; |
262 | kobject_set_name(&cdev->kobj, "%s", name); | 282 | kobject_set_name(&cdev->kobj, "%s", name); |
263 | for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/')) | 283 | for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/')) |
264 | *s = '!'; | 284 | *s = '!'; |
265 | 285 | ||
266 | err = cdev_add(cdev, MKDEV(cd->major, 0), 256); | 286 | err = cdev_add(cdev, MKDEV(cd->major, 0), 256); |
267 | if (err) | 287 | if (err) |
268 | goto out; | 288 | goto out; |
269 | 289 | ||
270 | cd->cdev = cdev; | 290 | cd->cdev = cdev; |
271 | 291 | ||
272 | return major ? 0 : cd->major; | 292 | return major ? 0 : cd->major; |
273 | out: | 293 | out: |
274 | kobject_put(&cdev->kobj); | 294 | kobject_put(&cdev->kobj); |
275 | out2: | 295 | out2: |
276 | kfree(__unregister_chrdev_region(cd->major, 0, 256)); | 296 | kfree(__unregister_chrdev_region(cd->major, 0, 256)); |
277 | return err; | 297 | return err; |
278 | } | 298 | } |
279 | 299 | ||
300 | /** | ||
301 | * unregister_chrdev_region() - return a range of device numbers | ||
302 | * @from: the first in the range of numbers to unregister | ||
303 | * @count: the number of device numbers to unregister | ||
304 | * | ||
305 | * This function will unregister a range of @count device numbers, | ||
306 | * starting with @from. The caller should normally be the one who | ||
307 | * allocated those numbers in the first place... | ||
308 | */ | ||
280 | void unregister_chrdev_region(dev_t from, unsigned count) | 309 | void unregister_chrdev_region(dev_t from, unsigned count) |
281 | { | 310 | { |
282 | dev_t to = from + count; | 311 | dev_t to = from + count; |
283 | dev_t n, next; | 312 | dev_t n, next; |
284 | 313 | ||
285 | for (n = from; n < to; n = next) { | 314 | for (n = from; n < to; n = next) { |
286 | next = MKDEV(MAJOR(n)+1, 0); | 315 | next = MKDEV(MAJOR(n)+1, 0); |
287 | if (next > to) | 316 | if (next > to) |
288 | next = to; | 317 | next = to; |
289 | kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n)); | 318 | kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n)); |
290 | } | 319 | } |
291 | } | 320 | } |
292 | 321 | ||
293 | int unregister_chrdev(unsigned int major, const char *name) | 322 | int unregister_chrdev(unsigned int major, const char *name) |
294 | { | 323 | { |
295 | struct char_device_struct *cd; | 324 | struct char_device_struct *cd; |
296 | cd = __unregister_chrdev_region(major, 0, 256); | 325 | cd = __unregister_chrdev_region(major, 0, 256); |
297 | if (cd && cd->cdev) | 326 | if (cd && cd->cdev) |
298 | cdev_del(cd->cdev); | 327 | cdev_del(cd->cdev); |
299 | kfree(cd); | 328 | kfree(cd); |
300 | return 0; | 329 | return 0; |
301 | } | 330 | } |
302 | 331 | ||
303 | static DEFINE_SPINLOCK(cdev_lock); | 332 | static DEFINE_SPINLOCK(cdev_lock); |
304 | 333 | ||
305 | static struct kobject *cdev_get(struct cdev *p) | 334 | static struct kobject *cdev_get(struct cdev *p) |
306 | { | 335 | { |
307 | struct module *owner = p->owner; | 336 | struct module *owner = p->owner; |
308 | struct kobject *kobj; | 337 | struct kobject *kobj; |
309 | 338 | ||
310 | if (owner && !try_module_get(owner)) | 339 | if (owner && !try_module_get(owner)) |
311 | return NULL; | 340 | return NULL; |
312 | kobj = kobject_get(&p->kobj); | 341 | kobj = kobject_get(&p->kobj); |
313 | if (!kobj) | 342 | if (!kobj) |
314 | module_put(owner); | 343 | module_put(owner); |
315 | return kobj; | 344 | return kobj; |
316 | } | 345 | } |
317 | 346 | ||
318 | void cdev_put(struct cdev *p) | 347 | void cdev_put(struct cdev *p) |
319 | { | 348 | { |
320 | if (p) { | 349 | if (p) { |
321 | struct module *owner = p->owner; | 350 | struct module *owner = p->owner; |
322 | kobject_put(&p->kobj); | 351 | kobject_put(&p->kobj); |
323 | module_put(owner); | 352 | module_put(owner); |
324 | } | 353 | } |
325 | } | 354 | } |
326 | 355 | ||
327 | /* | 356 | /* |
328 | * Called every time a character special file is opened | 357 | * Called every time a character special file is opened |
329 | */ | 358 | */ |
330 | int chrdev_open(struct inode * inode, struct file * filp) | 359 | int chrdev_open(struct inode * inode, struct file * filp) |
331 | { | 360 | { |
332 | struct cdev *p; | 361 | struct cdev *p; |
333 | struct cdev *new = NULL; | 362 | struct cdev *new = NULL; |
334 | int ret = 0; | 363 | int ret = 0; |
335 | 364 | ||
336 | spin_lock(&cdev_lock); | 365 | spin_lock(&cdev_lock); |
337 | p = inode->i_cdev; | 366 | p = inode->i_cdev; |
338 | if (!p) { | 367 | if (!p) { |
339 | struct kobject *kobj; | 368 | struct kobject *kobj; |
340 | int idx; | 369 | int idx; |
341 | spin_unlock(&cdev_lock); | 370 | spin_unlock(&cdev_lock); |
342 | kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); | 371 | kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); |
343 | if (!kobj) | 372 | if (!kobj) |
344 | return -ENXIO; | 373 | return -ENXIO; |
345 | new = container_of(kobj, struct cdev, kobj); | 374 | new = container_of(kobj, struct cdev, kobj); |
346 | spin_lock(&cdev_lock); | 375 | spin_lock(&cdev_lock); |
347 | p = inode->i_cdev; | 376 | p = inode->i_cdev; |
348 | if (!p) { | 377 | if (!p) { |
349 | inode->i_cdev = p = new; | 378 | inode->i_cdev = p = new; |
350 | inode->i_cindex = idx; | 379 | inode->i_cindex = idx; |
351 | list_add(&inode->i_devices, &p->list); | 380 | list_add(&inode->i_devices, &p->list); |
352 | new = NULL; | 381 | new = NULL; |
353 | } else if (!cdev_get(p)) | 382 | } else if (!cdev_get(p)) |
354 | ret = -ENXIO; | 383 | ret = -ENXIO; |
355 | } else if (!cdev_get(p)) | 384 | } else if (!cdev_get(p)) |
356 | ret = -ENXIO; | 385 | ret = -ENXIO; |
357 | spin_unlock(&cdev_lock); | 386 | spin_unlock(&cdev_lock); |
358 | cdev_put(new); | 387 | cdev_put(new); |
359 | if (ret) | 388 | if (ret) |
360 | return ret; | 389 | return ret; |
361 | filp->f_op = fops_get(p->ops); | 390 | filp->f_op = fops_get(p->ops); |
362 | if (!filp->f_op) { | 391 | if (!filp->f_op) { |
363 | cdev_put(p); | 392 | cdev_put(p); |
364 | return -ENXIO; | 393 | return -ENXIO; |
365 | } | 394 | } |
366 | if (filp->f_op->open) { | 395 | if (filp->f_op->open) { |
367 | lock_kernel(); | 396 | lock_kernel(); |
368 | ret = filp->f_op->open(inode,filp); | 397 | ret = filp->f_op->open(inode,filp); |
369 | unlock_kernel(); | 398 | unlock_kernel(); |
370 | } | 399 | } |
371 | if (ret) | 400 | if (ret) |
372 | cdev_put(p); | 401 | cdev_put(p); |
373 | return ret; | 402 | return ret; |
374 | } | 403 | } |
375 | 404 | ||
376 | void cd_forget(struct inode *inode) | 405 | void cd_forget(struct inode *inode) |
377 | { | 406 | { |
378 | spin_lock(&cdev_lock); | 407 | spin_lock(&cdev_lock); |
379 | list_del_init(&inode->i_devices); | 408 | list_del_init(&inode->i_devices); |
380 | inode->i_cdev = NULL; | 409 | inode->i_cdev = NULL; |
381 | spin_unlock(&cdev_lock); | 410 | spin_unlock(&cdev_lock); |
382 | } | 411 | } |
383 | 412 | ||
384 | static void cdev_purge(struct cdev *cdev) | 413 | static void cdev_purge(struct cdev *cdev) |
385 | { | 414 | { |
386 | spin_lock(&cdev_lock); | 415 | spin_lock(&cdev_lock); |
387 | while (!list_empty(&cdev->list)) { | 416 | while (!list_empty(&cdev->list)) { |
388 | struct inode *inode; | 417 | struct inode *inode; |
389 | inode = container_of(cdev->list.next, struct inode, i_devices); | 418 | inode = container_of(cdev->list.next, struct inode, i_devices); |
390 | list_del_init(&inode->i_devices); | 419 | list_del_init(&inode->i_devices); |
391 | inode->i_cdev = NULL; | 420 | inode->i_cdev = NULL; |
392 | } | 421 | } |
393 | spin_unlock(&cdev_lock); | 422 | spin_unlock(&cdev_lock); |
394 | } | 423 | } |
395 | 424 | ||
396 | /* | 425 | /* |
397 | * Dummy default file-operations: the only thing this does | 426 | * Dummy default file-operations: the only thing this does |
398 | * is contain the open that then fills in the correct operations | 427 | * is contain the open that then fills in the correct operations |
399 | * depending on the special file... | 428 | * depending on the special file... |
400 | */ | 429 | */ |
401 | const struct file_operations def_chr_fops = { | 430 | const struct file_operations def_chr_fops = { |
402 | .open = chrdev_open, | 431 | .open = chrdev_open, |
403 | }; | 432 | }; |
404 | 433 | ||
405 | static struct kobject *exact_match(dev_t dev, int *part, void *data) | 434 | static struct kobject *exact_match(dev_t dev, int *part, void *data) |
406 | { | 435 | { |
407 | struct cdev *p = data; | 436 | struct cdev *p = data; |
408 | return &p->kobj; | 437 | return &p->kobj; |
409 | } | 438 | } |
410 | 439 | ||
411 | static int exact_lock(dev_t dev, void *data) | 440 | static int exact_lock(dev_t dev, void *data) |
412 | { | 441 | { |
413 | struct cdev *p = data; | 442 | struct cdev *p = data; |
414 | return cdev_get(p) ? 0 : -1; | 443 | return cdev_get(p) ? 0 : -1; |
415 | } | 444 | } |
416 | 445 | ||
446 | /** | ||
447 | * cdev_add() - add a char device to the system | ||
448 | * @p: the cdev structure for the device | ||
449 | * @dev: the first device number for which this device is responsible | ||
450 | * @count: the number of consecutive minor numbers corresponding to this | ||
451 | * device | ||
452 | * | ||
453 | * cdev_add() adds the device represented by @p to the system, making it | ||
454 | * live immediately. A negative error code is returned on failure. | ||
455 | */ | ||
417 | int cdev_add(struct cdev *p, dev_t dev, unsigned count) | 456 | int cdev_add(struct cdev *p, dev_t dev, unsigned count) |
418 | { | 457 | { |
419 | p->dev = dev; | 458 | p->dev = dev; |
420 | p->count = count; | 459 | p->count = count; |
421 | return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p); | 460 | return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p); |
422 | } | 461 | } |
423 | 462 | ||
424 | static void cdev_unmap(dev_t dev, unsigned count) | 463 | static void cdev_unmap(dev_t dev, unsigned count) |
425 | { | 464 | { |
426 | kobj_unmap(cdev_map, dev, count); | 465 | kobj_unmap(cdev_map, dev, count); |
427 | } | 466 | } |
428 | 467 | ||
468 | /** | ||
469 | * cdev_del() - remove a cdev from the system | ||
470 | * @p: the cdev structure to be removed | ||
471 | * | ||
472 | * cdev_del() removes @p from the system, possibly freeing the structure | ||
473 | * itself. | ||
474 | */ | ||
429 | void cdev_del(struct cdev *p) | 475 | void cdev_del(struct cdev *p) |
430 | { | 476 | { |
431 | cdev_unmap(p->dev, p->count); | 477 | cdev_unmap(p->dev, p->count); |
432 | kobject_put(&p->kobj); | 478 | kobject_put(&p->kobj); |
433 | } | 479 | } |
434 | 480 | ||
435 | 481 | ||
436 | static void cdev_default_release(struct kobject *kobj) | 482 | static void cdev_default_release(struct kobject *kobj) |
437 | { | 483 | { |
438 | struct cdev *p = container_of(kobj, struct cdev, kobj); | 484 | struct cdev *p = container_of(kobj, struct cdev, kobj); |
439 | cdev_purge(p); | 485 | cdev_purge(p); |
440 | } | 486 | } |
441 | 487 | ||
442 | static void cdev_dynamic_release(struct kobject *kobj) | 488 | static void cdev_dynamic_release(struct kobject *kobj) |
443 | { | 489 | { |
444 | struct cdev *p = container_of(kobj, struct cdev, kobj); | 490 | struct cdev *p = container_of(kobj, struct cdev, kobj); |
445 | cdev_purge(p); | 491 | cdev_purge(p); |
446 | kfree(p); | 492 | kfree(p); |
447 | } | 493 | } |
448 | 494 | ||
449 | static struct kobj_type ktype_cdev_default = { | 495 | static struct kobj_type ktype_cdev_default = { |
450 | .release = cdev_default_release, | 496 | .release = cdev_default_release, |
451 | }; | 497 | }; |
452 | 498 | ||
453 | static struct kobj_type ktype_cdev_dynamic = { | 499 | static struct kobj_type ktype_cdev_dynamic = { |
454 | .release = cdev_dynamic_release, | 500 | .release = cdev_dynamic_release, |
455 | }; | 501 | }; |
456 | 502 | ||
503 | /** | ||
504 | * cdev_alloc() - allocate a cdev structure | ||
505 | * | ||
506 | * Allocates and returns a cdev structure, or NULL on failure. | ||
507 | */ | ||
457 | struct cdev *cdev_alloc(void) | 508 | struct cdev *cdev_alloc(void) |
458 | { | 509 | { |
459 | struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); | 510 | struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); |
460 | if (p) { | 511 | if (p) { |
461 | p->kobj.ktype = &ktype_cdev_dynamic; | 512 | p->kobj.ktype = &ktype_cdev_dynamic; |
462 | INIT_LIST_HEAD(&p->list); | 513 | INIT_LIST_HEAD(&p->list); |
463 | kobject_init(&p->kobj); | 514 | kobject_init(&p->kobj); |
464 | } | 515 | } |
465 | return p; | 516 | return p; |
466 | } | 517 | } |
467 | 518 | ||
519 | /** | ||
520 | * cdev_init() - initialize a cdev structure | ||
521 | * @cdev: the structure to initialize | ||
522 | * @fops: the file_operations for this device | ||
523 | * | ||
524 | * Initializes @cdev, remembering @fops, making it ready to add to the | ||
525 | * system with cdev_add(). | ||
526 | */ | ||
468 | void cdev_init(struct cdev *cdev, const struct file_operations *fops) | 527 | void cdev_init(struct cdev *cdev, const struct file_operations *fops) |
469 | { | 528 | { |
470 | memset(cdev, 0, sizeof *cdev); | 529 | memset(cdev, 0, sizeof *cdev); |
471 | INIT_LIST_HEAD(&cdev->list); | 530 | INIT_LIST_HEAD(&cdev->list); |
472 | cdev->kobj.ktype = &ktype_cdev_default; | 531 | cdev->kobj.ktype = &ktype_cdev_default; |
473 | kobject_init(&cdev->kobj); | 532 | kobject_init(&cdev->kobj); |
474 | cdev->ops = fops; | 533 | cdev->ops = fops; |
475 | } | 534 | } |
476 | 535 | ||
477 | static struct kobject *base_probe(dev_t dev, int *part, void *data) | 536 | static struct kobject *base_probe(dev_t dev, int *part, void *data) |
478 | { | 537 | { |
479 | if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0) | 538 | if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0) |
480 | /* Make old-style 2.4 aliases work */ | 539 | /* Make old-style 2.4 aliases work */ |
481 | request_module("char-major-%d", MAJOR(dev)); | 540 | request_module("char-major-%d", MAJOR(dev)); |
482 | return NULL; | 541 | return NULL; |
483 | } | 542 | } |
484 | 543 | ||
485 | void __init chrdev_init(void) | 544 | void __init chrdev_init(void) |
486 | { | 545 | { |
487 | cdev_map = kobj_map_init(base_probe, &chrdevs_lock); | 546 | cdev_map = kobj_map_init(base_probe, &chrdevs_lock); |
488 | } | 547 | } |
489 | 548 | ||
490 | 549 | ||
491 | /* Let modules do char dev stuff */ | 550 | /* Let modules do char dev stuff */ |
492 | EXPORT_SYMBOL(register_chrdev_region); | 551 | EXPORT_SYMBOL(register_chrdev_region); |
493 | EXPORT_SYMBOL(unregister_chrdev_region); | 552 | EXPORT_SYMBOL(unregister_chrdev_region); |
494 | EXPORT_SYMBOL(alloc_chrdev_region); | 553 | EXPORT_SYMBOL(alloc_chrdev_region); |
495 | EXPORT_SYMBOL(cdev_init); | 554 | EXPORT_SYMBOL(cdev_init); |
496 | EXPORT_SYMBOL(cdev_alloc); | 555 | EXPORT_SYMBOL(cdev_alloc); |
497 | EXPORT_SYMBOL(cdev_del); | 556 | EXPORT_SYMBOL(cdev_del); |
498 | EXPORT_SYMBOL(cdev_add); | 557 | EXPORT_SYMBOL(cdev_add); |
499 | EXPORT_SYMBOL(register_chrdev); | 558 | EXPORT_SYMBOL(register_chrdev); |
500 | EXPORT_SYMBOL(unregister_chrdev); | 559 | EXPORT_SYMBOL(unregister_chrdev); |
501 | EXPORT_SYMBOL(directly_mappable_cdev_bdi); | 560 | EXPORT_SYMBOL(directly_mappable_cdev_bdi); |
502 | 561 |