added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / staging / comedi / drivers / comedi_bond.c
blob9e5496f4f1ae9927be835a4519b7eac4674a17e2
1 /*
2 comedi/drivers/comedi_bond.c
3 A Comedi driver to 'bond' or merge multiple drivers and devices as one.
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 Copyright (C) 2005 Calin A. Culianu <calin@ajvar.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 Driver: comedi_bond
26 Description: A driver to 'bond' (merge) multiple subdevices from multiple
27 devices together as one.
28 Devices:
29 Author: ds
30 Updated: Mon, 10 Oct 00:18:25 -0500
31 Status: works
33 This driver allows you to 'bond' (merge) multiple comedi subdevices
34 (coming from possibly difference boards and/or drivers) together. For
35 example, if you had a board with 2 different DIO subdevices, and
36 another with 1 DIO subdevice, you could 'bond' them with this driver
37 so that they look like one big fat DIO subdevice. This makes writing
38 applications slightly easier as you don't have to worry about managing
39 different subdevices in the application -- you just worry about
40 indexing one linear array of channel id's.
42 Right now only DIO subdevices are supported as that's the personal itch
43 I am scratching with this driver. If you want to add support for AI and AO
44 subdevs, go right on ahead and do so!
46 Commands aren't supported -- although it would be cool if they were.
48 Configuration Options:
49 List of comedi-minors to bond. All subdevices of the same type
50 within each minor will be concatenated together in the order given here.
54 * The previous block comment is used to automatically generate
55 * documentation in Comedi and Comedilib. The fields:
57 * Driver: the name of the driver
58 * Description: a short phrase describing the driver. Don't list boards.
59 * Devices: a full list of the boards that attempt to be supported by
60 * the driver. Format is "(manufacturer) board name [comedi name]",
61 * where comedi_name is the name that is used to configure the board.
62 * See the comment near board_name: in the comedi_driver structure
63 * below. If (manufacturer) or [comedi name] is missing, the previous
64 * value is used.
65 * Author: you
66 * Updated: date when the _documentation_ was last updated. Use 'date -R'
67 * to get a value for this.
68 * Status: a one-word description of the status. Valid values are:
69 * works - driver works correctly on most boards supported, and
70 * passes comedi_test.
71 * unknown - unknown. Usually put there by ds.
72 * experimental - may not work in any particular release. Author
73 * probably wants assistance testing it.
74 * bitrotten - driver has not been update in a long time, probably
75 * doesn't work, and probably is missing support for significant
76 * Comedi interface features.
77 * untested - author probably wrote it "blind", and is believed to
78 * work, but no confirmation.
80 * These headers should be followed by a blank line, and any comments
81 * you wish to say about the driver. The comment area is the place
82 * to put any known bugs, limitations, unsupported features, supported
83 * command triggers, whether or not commands are supported on particular
84 * subdevices, etc.
86 * Somewhere in the comment should be information about configuration
87 * options that are used with comedi_config.
90 #include "../comedilib.h"
91 #include "../comedidev.h"
92 #include <linux/string.h>
94 /* The maxiumum number of channels per subdevice. */
95 #define MAX_CHANS 256
97 #define MODULE_NAME "comedi_bond"
98 #ifdef MODULE_LICENSE
99 MODULE_LICENSE("GPL");
100 #endif
101 #ifndef STR
102 # define STR1(x) #x
103 # define STR(x) STR1(x)
104 #endif
106 static int debug;
107 module_param(debug, int, 0644);
108 MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful"
109 "only to developers.");
111 #define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x)
112 #define DEBUG(x...) \
113 do { \
114 if (debug) \
115 printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \
116 } while (0)
117 #define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x)
118 #define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x)
119 MODULE_AUTHOR("Calin A. Culianu");
120 MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
121 "devices together as one. In the words of John Lennon: "
122 "'And the world will live as one...'");
125 * Board descriptions for two imaginary boards. Describing the
126 * boards in this way is optional, and completely driver-dependent.
127 * Some drivers use arrays such as this, other do not.
129 struct BondingBoard {
130 const char *name;
133 static const struct BondingBoard bondingBoards[] = {
135 .name = MODULE_NAME,
140 * Useful for shorthand access to the particular board structure
142 #define thisboard ((const struct BondingBoard *)dev->board_ptr)
144 struct BondedDevice {
145 comedi_t *dev;
146 unsigned minor;
147 unsigned subdev;
148 unsigned subdev_type;
149 unsigned nchans;
150 unsigned chanid_offset; /* The offset into our unified linear
151 channel-id's of chanid 0 on this
152 subdevice. */
155 /* this structure is for data unique to this hardware driver. If
156 several hardware drivers keep similar information in this structure,
157 feel free to suggest moving the variable to the comedi_device struct. */
158 struct Private {
159 # define MAX_BOARD_NAME 256
160 char name[MAX_BOARD_NAME];
161 struct BondedDevice **devs;
162 unsigned ndevs;
163 struct BondedDevice *chanIdDevMap[MAX_CHANS];
164 unsigned nchans;
168 * most drivers define the following macro to make it easy to
169 * access the private structure.
171 #define devpriv ((struct Private *)dev->private)
174 * The comedi_driver structure tells the Comedi core module
175 * which functions to call to configure/deconfigure (attach/detach)
176 * the board, and also about the kernel module that contains
177 * the device code.
179 static int bonding_attach(comedi_device *dev, comedi_devconfig *it);
180 static int bonding_detach(comedi_device *dev);
181 /** Build Private array of all devices.. */
182 static int doDevConfig(comedi_device *dev, comedi_devconfig *it);
183 static void doDevUnconfig(comedi_device *dev);
184 /* Ugly implementation of realloc that always copies memory around -- I'm lazy,
185 * what can I say? I like to do wasteful memcopies.. :) */
186 static void *Realloc(const void *ptr, size_t len, size_t old_len);
188 static comedi_driver driver_bonding = {
189 .driver_name = MODULE_NAME,
190 .module = THIS_MODULE,
191 .attach = bonding_attach,
192 .detach = bonding_detach,
193 /* It is not necessary to implement the following members if you are
194 * writing a driver for a ISA PnP or PCI card */
195 /* Most drivers will support multiple types of boards by
196 * having an array of board structures. These were defined
197 * in skel_boards[] above. Note that the element 'name'
198 * was first in the structure -- Comedi uses this fact to
199 * extract the name of the board without knowing any details
200 * about the structure except for its length.
201 * When a device is attached (by comedi_config), the name
202 * of the device is given to Comedi, and Comedi tries to
203 * match it by going through the list of board names. If
204 * there is a match, the address of the pointer is put
205 * into dev->board_ptr and driver->attach() is called.
207 * Note that these are not necessary if you can determine
208 * the type of board in software. ISA PnP, PCI, and PCMCIA
209 * devices are such boards.
211 .board_name = &bondingBoards[0].name,
212 .offset = sizeof(struct BondingBoard),
213 .num_names = sizeof(bondingBoards) / sizeof(struct BondingBoard),
216 static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
217 comedi_insn *insn, lsampl_t *data);
218 static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
219 comedi_insn *insn, lsampl_t *data);
222 * Attach is called by the Comedi core to configure the driver
223 * for a particular board. If you specified a board_name array
224 * in the driver structure, dev->board_ptr contains that
225 * address.
227 static int bonding_attach(comedi_device *dev, comedi_devconfig *it)
229 comedi_subdevice *s;
231 LOG_MSG("comedi%d\n", dev->minor);
234 * Allocate the private structure area. alloc_private() is a
235 * convenient macro defined in comedidev.h.
237 if (alloc_private(dev, sizeof(struct Private)) < 0)
238 return -ENOMEM;
241 * Setup our bonding from config params.. sets up our Private struct..
243 if (!doDevConfig(dev, it))
244 return -EINVAL;
247 * Initialize dev->board_name. Note that we can use the "thisboard"
248 * macro now, since we just initialized it in the last line.
250 dev->board_name = devpriv->name;
253 * Allocate the subdevice structures. alloc_subdevice() is a
254 * convenient macro defined in comedidev.h.
256 if (alloc_subdevices(dev, 1) < 0)
257 return -ENOMEM;
259 s = dev->subdevices + 0;
260 s->type = COMEDI_SUBD_DIO;
261 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
262 s->n_chan = devpriv->nchans;
263 s->maxdata = 1;
264 s->range_table = &range_digital;
265 s->insn_bits = bonding_dio_insn_bits;
266 s->insn_config = bonding_dio_insn_config;
268 LOG_MSG("attached with %u DIO channels coming from %u different "
269 "subdevices all bonded together. "
270 "John Lennon would be proud!\n",
271 devpriv->nchans, devpriv->ndevs);
273 return 1;
277 * _detach is called to deconfigure a device. It should deallocate
278 * resources.
279 * This function is also called when _attach() fails, so it should be
280 * careful not to release resources that were not necessarily
281 * allocated by _attach(). dev->private and dev->subdevices are
282 * deallocated automatically by the core.
284 static int bonding_detach(comedi_device *dev)
286 LOG_MSG("comedi%d: remove\n", dev->minor);
287 doDevUnconfig(dev);
288 return 0;
291 /* DIO devices are slightly special. Although it is possible to
292 * implement the insn_read/insn_write interface, it is much more
293 * useful to applications if you implement the insn_bits interface.
294 * This allows packed reading/writing of the DIO channels. The
295 * comedi core can convert between insn_bits and insn_read/write */
296 static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
297 comedi_insn *insn, lsampl_t *data)
299 #define LSAMPL_BITS (sizeof(lsampl_t)*8)
300 unsigned nchans = LSAMPL_BITS, num_done = 0, i;
301 if (insn->n != 2)
302 return -EINVAL;
304 if (devpriv->nchans < nchans)
305 nchans = devpriv->nchans;
307 /* The insn data is a mask in data[0] and the new data
308 * in data[1], each channel cooresponding to a bit. */
309 for (i = 0; num_done < nchans && i < devpriv->ndevs; ++i) {
310 struct BondedDevice *bdev = devpriv->devs[i];
311 /* Grab the channel mask and data of only the bits corresponding
312 to this subdevice.. need to shift them to zero position of
313 course. */
314 /* Bits corresponding to this subdev. */
315 lsampl_t subdevMask = ((1 << bdev->nchans) - 1);
316 lsampl_t writeMask, dataBits;
318 /* Argh, we have >= LSAMPL_BITS chans.. take all bits */
319 if (bdev->nchans >= LSAMPL_BITS)
320 subdevMask = (lsampl_t) (-1);
322 writeMask = (data[0] >> num_done) & subdevMask;
323 dataBits = (data[1] >> num_done) & subdevMask;
325 /* Read/Write the new digital lines */
326 if (comedi_dio_bitfield(bdev->dev, bdev->subdev, writeMask,
327 &dataBits) != 2)
328 return -EINVAL;
330 /* Make room for the new bits in data[1], the return value */
331 data[1] &= ~(subdevMask << num_done);
332 /* Put the bits in the return value */
333 data[1] |= (dataBits & subdevMask) << num_done;
334 /* Save the new bits to the saved state.. */
335 s->state = data[1];
337 num_done += bdev->nchans;
340 return insn->n;
343 static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
344 comedi_insn *insn, lsampl_t *data)
346 int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
347 unsigned int io;
348 struct BondedDevice *bdev;
350 if (chan < 0 || chan >= devpriv->nchans)
351 return -EINVAL;
352 bdev = devpriv->chanIdDevMap[chan];
354 /* The input or output configuration of each digital line is
355 * configured by a special insn_config instruction. chanspec
356 * contains the channel to be changed, and data[0] contains the
357 * value COMEDI_INPUT or COMEDI_OUTPUT. */
358 switch (data[0]) {
359 case INSN_CONFIG_DIO_OUTPUT:
360 io = COMEDI_OUTPUT; /* is this really necessary? */
361 io_bits |= 1 << chan;
362 break;
363 case INSN_CONFIG_DIO_INPUT:
364 io = COMEDI_INPUT; /* is this really necessary? */
365 io_bits &= ~(1 << chan);
366 break;
367 case INSN_CONFIG_DIO_QUERY:
368 data[1] =
369 (io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
370 return insn->n;
371 break;
372 default:
373 return -EINVAL;
374 break;
376 /* 'real' channel id for this subdev.. */
377 chan -= bdev->chanid_offset;
378 ret = comedi_dio_config(bdev->dev, bdev->subdev, chan, io);
379 if (ret != 1)
380 return -EINVAL;
381 /* Finally, save the new io_bits values since we didn't get
382 an error above. */
383 s->io_bits = io_bits;
384 return insn->n;
387 static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
389 void *newmem = kmalloc(newlen, GFP_KERNEL);
391 if (newmem && oldmem)
392 memcpy(newmem, oldmem, min(oldlen, newlen));
393 kfree(oldmem);
394 return newmem;
397 static int doDevConfig(comedi_device *dev, comedi_devconfig *it)
399 int i;
400 comedi_t *devs_opened[COMEDI_NUM_BOARD_MINORS];
402 memset(devs_opened, 0, sizeof(devs_opened));
403 devpriv->name[0] = 0;;
404 /* Loop through all comedi devices specified on the command-line,
405 building our device list */
406 for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) {
407 char file[] = "/dev/comediXXXXXX";
408 int minor = it->options[i];
409 comedi_t *d;
410 int sdev = -1, nchans, tmp;
411 struct BondedDevice *bdev = NULL;
413 if (minor < 0 || minor > COMEDI_NUM_BOARD_MINORS) {
414 ERROR("Minor %d is invalid!\n", minor);
415 return 0;
417 if (minor == dev->minor) {
418 ERROR("Cannot bond this driver to itself!\n");
419 return 0;
421 if (devs_opened[minor]) {
422 ERROR("Minor %d specified more than once!\n", minor);
423 return 0;
426 snprintf(file, sizeof(file), "/dev/comedi%u", minor);
427 file[sizeof(file) - 1] = 0;
429 d = devs_opened[minor] = comedi_open(file);
431 if (!d) {
432 ERROR("Minor %u could not be opened\n", minor);
433 return 0;
436 /* Do DIO, as that's all we support now.. */
437 while ((sdev = comedi_find_subdevice_by_type(d, COMEDI_SUBD_DIO,
438 sdev + 1)) > -1) {
439 nchans = comedi_get_n_channels(d, sdev);
440 if (nchans <= 0) {
441 ERROR("comedi_get_n_channels() returned %d "
442 "on minor %u subdev %d!\n",
443 nchans, minor, sdev);
444 return 0;
446 bdev = kmalloc(sizeof(*bdev), GFP_KERNEL);
447 if (!bdev) {
448 ERROR("Out of memory.\n");
449 return 0;
451 bdev->dev = d;
452 bdev->minor = minor;
453 bdev->subdev = sdev;
454 bdev->subdev_type = COMEDI_SUBD_DIO;
455 bdev->nchans = nchans;
456 bdev->chanid_offset = devpriv->nchans;
458 /* map channel id's to BondedDevice * pointer.. */
459 while (nchans--)
460 devpriv->chanIdDevMap[devpriv->nchans++] = bdev;
462 /* Now put bdev pointer at end of devpriv->devs array
463 * list.. */
465 /* ergh.. ugly.. we need to realloc :( */
466 tmp = devpriv->ndevs * sizeof(bdev);
467 devpriv->devs =
468 Realloc(devpriv->devs,
469 ++devpriv->ndevs * sizeof(bdev), tmp);
470 if (!devpriv->devs) {
471 ERROR("Could not allocate memory. "
472 "Out of memory?");
473 return 0;
476 devpriv->devs[devpriv->ndevs - 1] = bdev;
478 /** Append dev:subdev to devpriv->name */
479 char buf[20];
480 int left =
481 MAX_BOARD_NAME - strlen(devpriv->name) -
483 snprintf(buf, sizeof(buf), "%d:%d ", dev->minor,
484 bdev->subdev);
485 buf[sizeof(buf) - 1] = 0;
486 strncat(devpriv->name, buf, left);
492 if (!devpriv->nchans) {
493 ERROR("No channels found!\n");
494 return 0;
497 return 1;
500 static void doDevUnconfig(comedi_device *dev)
502 unsigned long devs_closed = 0;
504 if (devpriv) {
505 while (devpriv->ndevs-- && devpriv->devs) {
506 struct BondedDevice *bdev;
508 bdev = devpriv->devs[devpriv->ndevs];
509 if (!bdev)
510 continue;
511 if (!(devs_closed & (0x1 << bdev->minor))) {
512 comedi_close(bdev->dev);
513 devs_closed |= (0x1 << bdev->minor);
515 kfree(bdev);
517 kfree(devpriv->devs);
518 devpriv->devs = NULL;
519 kfree(devpriv);
520 dev->private = NULL;
524 static int __init init(void)
526 return comedi_driver_register(&driver_bonding);
529 static void __exit cleanup(void)
531 comedi_driver_unregister(&driver_bonding);
534 module_init(init);
535 module_exit(cleanup);