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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
|
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>6.2. Generic functionality</title><link rel="stylesheet" type="text/css" href="comedilib.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="index.html" title="Comedi"><link rel="up" href="driverwriting.html" title="6. Writing a Comedi driver"><link rel="prev" href="driverwriting.html" title="6. Writing a Comedi driver"><link rel="next" href="boardspecific.html" title="6.3. Board-specific functionality"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.2.
Generic functionality
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="driverwriting.html">Prev</a> </td><th width="60%" align="center">6.
Writing a <acronym class="acronym">Comedi</acronym> driver
</th><td width="20%" align="right"> <a accesskey="n" href="boardspecific.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="comedikernelgeneric"></a>6.2.
Generic functionality
</h3></div></div></div><div class="toc"><dl class="toc"><dt><span class="section"><a href="comedikernelgeneric.html#driverdatastructures">6.2.1.
Data structures
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#driversupportfunctions">6.2.2.
Generic driver support functions
</a></span></dt></dl></div><p>
The major include files of the kernel-space part of <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> are:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
<code class="filename">include/linux/comedidev.h</code>: the
header file for kernel-only structures (device, subdevice, async
(i.e., buffer/event/interrupt/callback functionality for asynchronous
DAQ in a <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> command), driver, lrange), variables, inline functions
and constants.
</p></li><li class="listitem"><p>
<code class="filename">include/linux/comedi_rt.h</code>:
all the real-time stuff, such as management of ISR in RTAI and
RTLinux/Free, and spinlocks for atomic sections.
</p></li><li class="listitem"><p>
<code class="filename">include/linux/comedilib.h</code>: the header file for
the kernel library of <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> (<code class="systemitem">kcomedilib</code> module).
</p></li></ul></div><p>
</p><p>
From all the relevant <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> device driver code that is found in the
<code class="filename">comedi</code> kernel module source directory,
the <span class="strong"><strong>generic</strong></span> functionality is
contained in two parts:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
A couple of <code class="filename">C</code> files contain the <span class="strong"><strong>infrastructural support</strong></span>.
From these <code class="filename">C</code> files, it's especially the
<code class="filename">comedi_fops.c</code> file that implements what makes
<a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> into what people want to use it for: a library that has
solved 90% of the DAQ device driver efforts, once and for all.
</p></li><li class="listitem"><p>
For <span class="strong"><strong>real-time</strong></span> applications,
the subdirectory <code class="filename">kcomedilib</code>
implements an interface in the kernel that is similar to the <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a>
interface accessible through the
<a class="link" href="functionreference.html" title="5.4. Functions">user-space Comedi library</a>.
</p><p>
There are some differences in what is possible and/or needed
in kernel-space and in user-space, so the functionalities offered in
<code class="filename">kcomedilib</code> are not an exact copy
of the user-space library. For example, locking, interrupt handling,
real-time execution, callback handling, etc., are only available in
kernel-space.
</p><p>
Most drivers don't make use (yet) of these real-time functionalities.
</p></li></ul></div><p>
</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="driverdatastructures"></a>6.2.1.
Data structures
</h4></div></div></div><div class="toc"><dl class="toc"><dt><span class="section"><a href="comedikernelgeneric.html#comedilrange">6.2.1.1.
<span class="type">comedi_lrange</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comedisubdevice">6.2.1.2.
<span class="type">comedi_subdevice</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comedidevice">6.2.1.3.
<span class="type">comedi_device</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comediasync">6.2.1.4.
<span class="type">comedi_async</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comedidriver">6.2.1.5.
<span class="type">comedi_driver</span>
</a></span></dt></dl></div><p>
This Section explains the generic data structures that a device driver
interacts with:
</p><pre class="programlisting">
typedef struct comedi_lrange_struct <a class="link" href="comedikernelgeneric.html#comedilrange" title="6.2.1.1. comedi_lrange">comedi_lrange</a>;
typedef struct comedi_subdevice_struct <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a>;
typedef struct comedi_device_struct <a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a>:
typedef struct comedi_async_struct <a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4. comedi_async">comedi_async</a>
typedef struct comedi_driver_struct <a class="link" href="comedikernelgeneric.html#comedidriver" title="6.2.1.5. comedi_driver">comedi_driver</a>;
</pre><p>
They can be found in
<code class="filename">include/linux/comedidev.h</code>.
Most of the fields are filled in by the <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> infrastructure, but
there are still quite a handful that your driver must provide or use.
As for the user-level <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a>, each of the hierarchical layers has
its own data structures: range (<span class="type">comedi_lrange</span>),
subdevice, and device.
</p><p>
Note that these kernel-space data structures have similar names as
their
<a class="link" href="datatypesstructures.html" title="5.3. Data types and structures">user-space equivalents</a>, but
they have a different (kernel-side) view on the DAQ problem and a
different meaning: they encode the interaction with the
<span class="emphasis"><em>hardware</em></span>, not with the <span class="emphasis"><em>user</em></span>.
</p><p>
However, the <span class="type"><a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8. comedi_insn">comedi_insn</a></span>
and <span class="type"><a class="link" href="datatypesstructures.html#ref-type-comedi-cmd" title="5.3.7. comedi_cmd">comedi_cmd</a></span>
data structures are shared between user-space and kernel-space: this
should come as no surprise, since these data structures contain all
information that the user-space program must transfer to the
kernel-space driver for each acquisition.
</p><p>
In addition to these data entities that are also known at the user
level (device, sub-device, channel), the device driver level provides
two more data structures which the application programmer doesn't get
in touch with: the data structure
<span class="type"><a class="link" href="comedikernelgeneric.html#comedidriver" title="6.2.1.5. comedi_driver">comedi_driver</a></span>
that stores the device driver information that is relevant at the
operating system level, and the data structure
<span class="type"><a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4. comedi_async">comedi_async</a></span> that stores the
information about all <span class="emphasis"><em>asynchronous</em></span> activities
(interrupts, callbacks and events).
</p><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedilrange"></a>6.2.1.1.
<span class="type">comedi_lrange</span>
</h5></div></div></div><p>
The channel information is simple, since it contains only the signal
range information:
</p><pre class="programlisting">
struct comedi_lrange_struct{
int length;
<a class="link" href="datatypesstructures.html#ref-type-comedi-krange" title="5.3.10. comedi_krange">comedi_krange</a> range[GCC_ZERO_LENGTH_ARRAY];
};
</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedisubdevice"></a>6.2.1.2.
<span class="type">comedi_subdevice</span>
</h5></div></div></div><p>
The subdevice is the smallest <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> entity that can be used for
<span class="quote">“<span class="quote">stand-alone</span>”</span> DAQ, so it is no surprise that it is
quite big:
</p><pre class="programlisting">
struct comedi_subdevice_struct{
int type;
int n_chan;
int subdev_flags;
int len_chanlist; /* maximum length of channel/gain list */
void *private;
<a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4. comedi_async">comedi_async</a> *async;
void *lock;
void *busy;
unsigned int runflags;
int io_bits;
<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> maxdata; /* if maxdata==0, use list */
<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> *maxdata_list; /* list is channel specific */
unsigned int flags;
unsigned int *flaglist;
<a class="link" href="comedikernelgeneric.html#comedilrange" title="6.2.1.1. comedi_lrange">comedi_lrange</a> *range_table;
<a class="link" href="comedikernelgeneric.html#comedilrange" title="6.2.1.1. comedi_lrange">comedi_lrange</a> **range_table_list;
unsigned int *chanlist; /* driver-owned chanlist (not used) */
int (*insn_read)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8. comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> *);
int (*insn_write)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8. comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> *);
int (*insn_bits)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8. comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> *);
int (*insn_config)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8. comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> *);
int (*do_cmd)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *);
int (*do_cmdtest)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-cmd" title="5.3.7. comedi_cmd">comedi_cmd</a> *);
int (*poll)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *);
int (*cancel)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *);
int (*buf_change)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *s,unsigned long new_size);
void (*munge)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *, <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *s, void *data, unsigned int num_bytes, unsigned int start_chan_index );
unsigned int state;
};
</pre><p>
The function pointers <em class="structfield"><code>insn_read</code></em> …
<em class="structfield"><code>cancel</code></em> .
offer (pointers to) the standardized
<a class="link" href="functionreference.html" title="5.4. Functions">user-visible API</a>
that every subdevice should offer; every device driver has to fill
in these functions with their board-specific implementations.
(Functionality for which <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> provides generic functions will, by
definition, not show up in the device driver data structures.)
</p><p>
The <em class="structfield"><code>buf_change</code></em> and <em class="structfield"><code>munge</code></em>
function pointers offer functionality that is not visible to the user and for
which the device driver writer must provide a board-specific
implementation:
<code class="function">buf_change</code> is called when a change in the
data buffer requires handling; <code class="function">munge</code> transforms
different bit-representations of DAQ values, for example from
<span class="emphasis"><em>unsigned</em></span> to <span class="emphasis"><em>2's complement</em></span>.
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedidevice"></a>6.2.1.3.
<span class="type">comedi_device</span>
</h5></div></div></div><p>
The last data structure stores the information at the
<span class="emphasis"><em>device</em></span> level:
</p><pre class="programlisting">
struct comedi_device_struct{
int use_count;
<a class="link" href="comedikernelgeneric.html#comedidriver" title="6.2.1.5. comedi_driver">comedi_driver</a> *driver;
void *private;
kdev_t minor;
char *board_name;
const void *board_ptr;
int attached;
int rt;
spinlock_t spinlock;
int in_request_module;
int n_subdevices;
<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *subdevices;
int options[COMEDI_NDEVCONFOPTS];
/* dumb */
int iobase;
int irq;
<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *read_subdev;
wait_queue_head_t read_wait;
<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *write_subdev;
wait_queue_head_t write_wait;
struct fasync_struct *async_queue;
void (*open)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev);
void (*close)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev);
};
</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comediasync"></a>6.2.1.4.
<span class="type">comedi_async</span>
</h5></div></div></div><p>
The following data structure contains all relevant information:
addresses and sizes of buffers, pointers to the actual data, and the
information needed for
<a class="link" href="drivercallbacks.html" title="6.4. Callbacks, events and interrupts">event handling</a>:
</p><pre class="programlisting">
struct comedi_async_struct{
void *prealloc_buf; /* pre-allocated buffer */
unsigned int prealloc_bufsz; /* buffer size, in bytes */
unsigned long *buf_page_list; /* physical address of each page */
unsigned int max_bufsize; /* maximum buffer size, bytes */
unsigned int mmap_count; /* current number of mmaps of prealloc_buf */
volatile unsigned int buf_write_count; /* byte count for writer (write completed) */
volatile unsigned int buf_write_alloc_count; /* byte count for writer (allocated for writing) */
volatile unsigned int buf_read_count; /* byte count for reader (read completed)*/
unsigned int buf_write_ptr; /* buffer marker for writer */
unsigned int buf_read_ptr; /* buffer marker for reader */
unsigned int cur_chan; /* useless channel marker for interrupt */
/* number of bytes that have been received for current scan */
unsigned int scan_progress;
/* keeps track of where we are in chanlist as for munging */
unsigned int munge_chan;
unsigned int events; /* events that have occurred */
<a class="link" href="datatypesstructures.html#ref-type-comedi-cmd" title="5.3.7. comedi_cmd">comedi_cmd</a> cmd;
// callback stuff
unsigned int cb_mask;
int (*cb_func)(unsigned int flags,void *);
void *cb_arg;
int (*inttrig)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *s,unsigned int x);
};
</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedidriver"></a>6.2.1.5.
<span class="type">comedi_driver</span>
</h5></div></div></div><p>
</p><pre class="programlisting">
struct comedi_driver_struct{
struct comedi_driver_struct *next;
char *driver_name;
struct module *module;
int (*attach)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *,comedi_devconfig *);
int (*detach)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *);
/* number of elements in board_name and board_id arrays */
unsigned int num_names;
void *board_name;
/* offset in bytes from one board name pointer to the next */
int offset;
};
</pre><p>
</p></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="driversupportfunctions"></a>6.2.2.
Generic driver support functions
</h4></div></div></div><p>
The directory
<code class="filename">comedi</code> contains a large set of
support functions. Some of the most important ones are given below.
</p><p>
From <code class="filename">comedi/comedi_fops.c</code>, functions to handle the
hardware events (which also runs the registered callback function), to
get data in and out of the software data buffer, and to parse the
incoming functional requests:
</p><pre class="programlisting">
void comedi_event(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2. comedi_subdevice">comedi_subdevice</a> *s,unsigned int mask);
int comedi_buf_put(<a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4. comedi_async">comedi_async</a> *async, <a class="link" href="datatypesstructures.html#ref-type-sampl-t" title="5.3.3. sampl_t">sampl_t</a> x);
int comedi_buf_get(<a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4. comedi_async">comedi_async</a> *async, <a class="link" href="datatypesstructures.html#ref-type-sampl-t" title="5.3.3. sampl_t">sampl_t</a> *x);
static int parse_insn(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8. comedi_insn">comedi_insn</a> *insn,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4. lsampl_t">lsampl_t</a> *data,void *file);
</pre><p>
The file <code class="filename">comedi/kcomedilib/kcomedilib_main.c</code> provides
functions to register a callback, to poll an ongoing data acquisition,
and to print an error message:
</p><pre class="programlisting">
int comedi_register_callback(<a class="link" href="datatypesstructures.html#ref-type-comedi-t" title="5.3.2. comedi_t">comedi_t</a> *d,unsigned int subdevice, unsigned int mask,int (*cb)(unsigned int,void *),void *arg);
int comedi_poll(<a class="link" href="datatypesstructures.html#ref-type-comedi-t" title="5.3.2. comedi_t">comedi_t</a> *d, unsigned int subdevice);
void comedi_perror(const char *message);
</pre><p>
The file <code class="filename">comedi/rt.c</code> provides interrupt handling
for real-time tasks (one interrupt per <span class="emphasis"><em>device</em></span>!):
</p><pre class="programlisting">
int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *), unsigned long flags,const char *device,<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev_id);
void comedi_free_irq(unsigned int irq,<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3. comedi_device">comedi_device</a> *dev_id)
</pre><p>
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="driverwriting.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="driverwriting.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="boardspecific.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6.
Writing a <acronym class="acronym">Comedi</acronym> driver
</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 6.3.
Board-specific functionality
</td></tr></table></div></body></html>
|