Staging: comedi: pcmcia irq fixes
[linux-2.6/mini2440.git] / drivers / staging / comedi / drivers / cb_das16_cs.c
blob80c0df8656f317d5517d49bd2df494a95fb10f13
1 /*
2 comedi/drivers/das16cs.c
3 Driver for Computer Boards PC-CARD DAS16/16.
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 Driver: cb_das16_cs
25 Description: Computer Boards PC-CARD DAS16/16
26 Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO
27 Author: ds
28 Updated: Mon, 04 Nov 2002 20:04:21 -0800
29 Status: experimental
34 #include <linux/interrupt.h>
35 #include "../comedidev.h"
36 #include <linux/delay.h>
37 #include <linux/pci.h>
39 #include <pcmcia/cs_types.h>
40 #include <pcmcia/cs.h>
41 #include <pcmcia/cistpl.h>
42 #include <pcmcia/ds.h>
44 #include "8253.h"
46 #define DAS16CS_SIZE 18
48 #define DAS16CS_ADC_DATA 0
49 #define DAS16CS_DIO_MUX 2
50 #define DAS16CS_MISC1 4
51 #define DAS16CS_MISC2 6
52 #define DAS16CS_CTR0 8
53 #define DAS16CS_CTR1 10
54 #define DAS16CS_CTR2 12
55 #define DAS16CS_CTR_CONTROL 14
56 #define DAS16CS_DIO 16
58 struct das16cs_board {
59 const char *name;
60 int device_id;
61 int n_ao_chans;
63 static const struct das16cs_board das16cs_boards[] = {
65 .device_id = 0x0000, /* unknown */
66 .name = "PC-CARD DAS16/16",
67 .n_ao_chans = 0,
70 .device_id = 0x0039,
71 .name = "PC-CARD DAS16/16-AO",
72 .n_ao_chans = 2,
75 .device_id = 0x4009,
76 .name = "PCM-DAS16s/16",
77 .n_ao_chans = 0,
81 #define n_boards ARRAY_SIZE(das16cs_boards)
82 #define thisboard ((const struct das16cs_board *)dev->board_ptr)
84 struct das16cs_private {
85 struct pcmcia_device *link;
87 unsigned int ao_readback[2];
88 unsigned short status1;
89 unsigned short status2;
91 #define devpriv ((struct das16cs_private *)dev->private)
93 static int das16cs_attach(struct comedi_device *dev,
94 struct comedi_devconfig *it);
95 static int das16cs_detach(struct comedi_device *dev);
96 static struct comedi_driver driver_das16cs = {
97 .driver_name = "cb_das16_cs",
98 .module = THIS_MODULE,
99 .attach = das16cs_attach,
100 .detach = das16cs_detach,
103 static struct pcmcia_device *cur_dev = NULL;
105 static const struct comedi_lrange das16cs_ai_range = { 4, {
106 RANGE(-10, 10),
107 RANGE(-5, 5),
108 RANGE(-2.5, 2.5),
109 RANGE(-1.25, 1.25),
113 static irqreturn_t das16cs_interrupt(int irq, void *d);
114 static int das16cs_ai_rinsn(struct comedi_device *dev,
115 struct comedi_subdevice *s,
116 struct comedi_insn *insn, unsigned int *data);
117 static int das16cs_ai_cmd(struct comedi_device *dev,
118 struct comedi_subdevice *s);
119 static int das16cs_ai_cmdtest(struct comedi_device *dev,
120 struct comedi_subdevice *s,
121 struct comedi_cmd *cmd);
122 static int das16cs_ao_winsn(struct comedi_device *dev,
123 struct comedi_subdevice *s,
124 struct comedi_insn *insn, unsigned int *data);
125 static int das16cs_ao_rinsn(struct comedi_device *dev,
126 struct comedi_subdevice *s,
127 struct comedi_insn *insn, unsigned int *data);
128 static int das16cs_dio_insn_bits(struct comedi_device *dev,
129 struct comedi_subdevice *s,
130 struct comedi_insn *insn, unsigned int *data);
131 static int das16cs_dio_insn_config(struct comedi_device *dev,
132 struct comedi_subdevice *s,
133 struct comedi_insn *insn,
134 unsigned int *data);
135 static int das16cs_timer_insn_read(struct comedi_device *dev,
136 struct comedi_subdevice *s,
137 struct comedi_insn *insn,
138 unsigned int *data);
139 static int das16cs_timer_insn_config(struct comedi_device *dev,
140 struct comedi_subdevice *s,
141 struct comedi_insn *insn,
142 unsigned int *data);
144 static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link)
146 tuple_t tuple;
147 u_short buf[128];
148 int prodid = 0;
150 tuple.TupleData = (cisdata_t *) buf;
151 tuple.TupleOffset = 0;
152 tuple.TupleDataMax = 255;
153 tuple.DesiredTuple = CISTPL_MANFID;
154 tuple.Attributes = TUPLE_RETURN_COMMON;
155 if ((pcmcia_get_first_tuple(link, &tuple) == 0) &&
156 (pcmcia_get_tuple_data(link, &tuple) == 0)) {
157 prodid = le16_to_cpu(buf[1]);
160 return prodid;
163 static const struct das16cs_board *das16cs_probe(struct comedi_device *dev,
164 struct pcmcia_device *link)
166 int id;
167 int i;
169 id = get_prodid(dev, link);
171 for (i = 0; i < n_boards; i++) {
172 if (das16cs_boards[i].device_id == id) {
173 return das16cs_boards + i;
177 printk("unknown board!\n");
179 return NULL;
182 static int das16cs_attach(struct comedi_device *dev,
183 struct comedi_devconfig *it)
185 struct pcmcia_device *link;
186 struct comedi_subdevice *s;
187 int ret;
188 int i;
190 printk("comedi%d: cb_das16_cs: ", dev->minor);
192 link = cur_dev; /* XXX hack */
193 if (!link)
194 return -EIO;
196 dev->iobase = link->io.BasePort1;
197 printk("I/O base=0x%04lx ", dev->iobase);
199 printk("fingerprint:\n");
200 for (i = 0; i < 48; i += 2) {
201 printk("%04x ", inw(dev->iobase + i));
203 printk("\n");
205 ret = request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
206 IRQF_SHARED, "cb_das16_cs", dev);
207 if (ret < 0) {
208 return ret;
210 dev->irq = link->irq.AssignedIRQ;
211 printk("irq=%u ", dev->irq);
213 dev->board_ptr = das16cs_probe(dev, link);
214 if (!dev->board_ptr)
215 return -EIO;
217 dev->board_name = thisboard->name;
219 if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
220 return -ENOMEM;
222 if (alloc_subdevices(dev, 4) < 0)
223 return -ENOMEM;
225 s = dev->subdevices + 0;
226 dev->read_subdev = s;
227 /* analog input subdevice */
228 s->type = COMEDI_SUBD_AI;
229 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
230 s->n_chan = 16;
231 s->maxdata = 0xffff;
232 s->range_table = &das16cs_ai_range;
233 s->len_chanlist = 16;
234 s->insn_read = das16cs_ai_rinsn;
235 s->do_cmd = das16cs_ai_cmd;
236 s->do_cmdtest = das16cs_ai_cmdtest;
238 s = dev->subdevices + 1;
239 /* analog output subdevice */
240 if (thisboard->n_ao_chans) {
241 s->type = COMEDI_SUBD_AO;
242 s->subdev_flags = SDF_WRITABLE;
243 s->n_chan = thisboard->n_ao_chans;
244 s->maxdata = 0xffff;
245 s->range_table = &range_bipolar10;
246 s->insn_write = &das16cs_ao_winsn;
247 s->insn_read = &das16cs_ao_rinsn;
250 s = dev->subdevices + 2;
251 /* digital i/o subdevice */
252 if (1) {
253 s->type = COMEDI_SUBD_DIO;
254 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
255 s->n_chan = 8;
256 s->maxdata = 1;
257 s->range_table = &range_digital;
258 s->insn_bits = das16cs_dio_insn_bits;
259 s->insn_config = das16cs_dio_insn_config;
260 } else {
261 s->type = COMEDI_SUBD_UNUSED;
264 s = dev->subdevices + 3;
265 /* timer subdevice */
266 if (0) {
267 s->type = COMEDI_SUBD_TIMER;
268 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
269 s->n_chan = 1;
270 s->maxdata = 0xff;
271 s->range_table = &range_unknown;
272 s->insn_read = das16cs_timer_insn_read;
273 s->insn_config = das16cs_timer_insn_config;
274 } else {
275 s->type = COMEDI_SUBD_UNUSED;
278 printk("attached\n");
280 return 1;
283 static int das16cs_detach(struct comedi_device *dev)
285 printk("comedi%d: das16cs: remove\n", dev->minor);
287 if (dev->irq) {
288 free_irq(dev->irq, dev);
291 return 0;
294 static irqreturn_t das16cs_interrupt(int irq, void *d)
296 /* struct comedi_device *dev = d; */
297 return IRQ_HANDLED;
301 * "instructions" read/write data in "one-shot" or "software-triggered"
302 * mode.
304 static int das16cs_ai_rinsn(struct comedi_device *dev,
305 struct comedi_subdevice *s,
306 struct comedi_insn *insn, unsigned int *data)
308 int i;
309 int to;
310 int aref;
311 int range;
312 int chan;
313 static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
315 chan = CR_CHAN(insn->chanspec);
316 aref = CR_AREF(insn->chanspec);
317 range = CR_RANGE(insn->chanspec);
319 outw(chan, dev->iobase + 2);
321 devpriv->status1 &= ~0xf320;
322 devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
323 outw(devpriv->status1, dev->iobase + 4);
325 devpriv->status2 &= ~0xff00;
326 devpriv->status2 |= range_bits[range];
327 outw(devpriv->status2, dev->iobase + 6);
329 for (i = 0; i < insn->n; i++) {
330 outw(0, dev->iobase);
332 #define TIMEOUT 1000
333 for (to = 0; to < TIMEOUT; to++) {
334 if (inw(dev->iobase + 4) & 0x0080)
335 break;
337 if (to == TIMEOUT) {
338 printk("cb_das16_cs: ai timeout\n");
339 return -ETIME;
341 data[i] = (unsigned short)inw(dev->iobase + 0);
344 return i;
347 static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
349 return -EINVAL;
352 static int das16cs_ai_cmdtest(struct comedi_device *dev,
353 struct comedi_subdevice *s,
354 struct comedi_cmd *cmd)
356 int err = 0;
357 int tmp;
359 /* cmdtest tests a particular command to see if it is valid.
360 * Using the cmdtest ioctl, a user can create a valid cmd
361 * and then have it executes by the cmd ioctl.
363 * cmdtest returns 1,2,3,4 or 0, depending on which tests
364 * the command passes. */
366 /* step 1: make sure trigger sources are trivially valid */
368 tmp = cmd->start_src;
369 cmd->start_src &= TRIG_NOW;
370 if (!cmd->start_src || tmp != cmd->start_src)
371 err++;
373 tmp = cmd->scan_begin_src;
374 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
375 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
376 err++;
378 tmp = cmd->convert_src;
379 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
380 if (!cmd->convert_src || tmp != cmd->convert_src)
381 err++;
383 tmp = cmd->scan_end_src;
384 cmd->scan_end_src &= TRIG_COUNT;
385 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
386 err++;
388 tmp = cmd->stop_src;
389 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
390 if (!cmd->stop_src || tmp != cmd->stop_src)
391 err++;
393 if (err)
394 return 1;
396 /* step 2: make sure trigger sources are unique and mutually compatible */
398 /* note that mutual compatiblity is not an issue here */
399 if (cmd->scan_begin_src != TRIG_TIMER &&
400 cmd->scan_begin_src != TRIG_EXT)
401 err++;
402 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
403 err++;
404 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
405 err++;
407 if (err)
408 return 2;
410 /* step 3: make sure arguments are trivially compatible */
412 if (cmd->start_arg != 0) {
413 cmd->start_arg = 0;
414 err++;
416 #define MAX_SPEED 10000 /* in nanoseconds */
417 #define MIN_SPEED 1000000000 /* in nanoseconds */
419 if (cmd->scan_begin_src == TRIG_TIMER) {
420 if (cmd->scan_begin_arg < MAX_SPEED) {
421 cmd->scan_begin_arg = MAX_SPEED;
422 err++;
424 if (cmd->scan_begin_arg > MIN_SPEED) {
425 cmd->scan_begin_arg = MIN_SPEED;
426 err++;
428 } else {
429 /* external trigger */
430 /* should be level/edge, hi/lo specification here */
431 /* should specify multiple external triggers */
432 if (cmd->scan_begin_arg > 9) {
433 cmd->scan_begin_arg = 9;
434 err++;
437 if (cmd->convert_src == TRIG_TIMER) {
438 if (cmd->convert_arg < MAX_SPEED) {
439 cmd->convert_arg = MAX_SPEED;
440 err++;
442 if (cmd->convert_arg > MIN_SPEED) {
443 cmd->convert_arg = MIN_SPEED;
444 err++;
446 } else {
447 /* external trigger */
448 /* see above */
449 if (cmd->convert_arg > 9) {
450 cmd->convert_arg = 9;
451 err++;
455 if (cmd->scan_end_arg != cmd->chanlist_len) {
456 cmd->scan_end_arg = cmd->chanlist_len;
457 err++;
459 if (cmd->stop_src == TRIG_COUNT) {
460 if (cmd->stop_arg > 0x00ffffff) {
461 cmd->stop_arg = 0x00ffffff;
462 err++;
464 } else {
465 /* TRIG_NONE */
466 if (cmd->stop_arg != 0) {
467 cmd->stop_arg = 0;
468 err++;
472 if (err)
473 return 3;
475 /* step 4: fix up any arguments */
477 if (cmd->scan_begin_src == TRIG_TIMER) {
478 unsigned int div1, div2;
480 tmp = cmd->scan_begin_arg;
481 i8253_cascade_ns_to_timer(100, &div1, &div2,
482 &cmd->scan_begin_arg,
483 cmd->flags & TRIG_ROUND_MASK);
484 if (tmp != cmd->scan_begin_arg)
485 err++;
487 if (cmd->convert_src == TRIG_TIMER) {
488 unsigned int div1, div2;
490 tmp = cmd->convert_arg;
491 i8253_cascade_ns_to_timer(100, &div1, &div2,
492 &cmd->scan_begin_arg,
493 cmd->flags & TRIG_ROUND_MASK);
494 if (tmp != cmd->convert_arg)
495 err++;
496 if (cmd->scan_begin_src == TRIG_TIMER &&
497 cmd->scan_begin_arg <
498 cmd->convert_arg * cmd->scan_end_arg) {
499 cmd->scan_begin_arg =
500 cmd->convert_arg * cmd->scan_end_arg;
501 err++;
505 if (err)
506 return 4;
508 return 0;
511 static int das16cs_ao_winsn(struct comedi_device *dev,
512 struct comedi_subdevice *s,
513 struct comedi_insn *insn, unsigned int *data)
515 int i;
516 int chan = CR_CHAN(insn->chanspec);
517 unsigned short status1;
518 unsigned short d;
519 int bit;
521 for (i = 0; i < insn->n; i++) {
522 devpriv->ao_readback[chan] = data[i];
523 d = data[i];
525 outw(devpriv->status1, dev->iobase + 4);
526 udelay(1);
528 status1 = devpriv->status1 & ~0xf;
529 if (chan)
530 status1 |= 0x0001;
531 else
532 status1 |= 0x0008;
534 /* printk("0x%04x\n",status1);*/
535 outw(status1, dev->iobase + 4);
536 udelay(1);
538 for (bit = 15; bit >= 0; bit--) {
539 int b = (d >> bit) & 0x1;
540 b <<= 1;
541 /* printk("0x%04x\n",status1 | b | 0x0000);*/
542 outw(status1 | b | 0x0000, dev->iobase + 4);
543 udelay(1);
544 /* printk("0x%04x\n",status1 | b | 0x0004);*/
545 outw(status1 | b | 0x0004, dev->iobase + 4);
546 udelay(1);
548 /* make high both DAC0CS and DAC1CS to load
549 new data and update analog output*/
550 outw(status1 | 0x9, dev->iobase + 4);
553 return i;
556 /* AO subdevices should have a read insn as well as a write insn.
557 * Usually this means copying a value stored in devpriv. */
558 static int das16cs_ao_rinsn(struct comedi_device *dev,
559 struct comedi_subdevice *s,
560 struct comedi_insn *insn, unsigned int *data)
562 int i;
563 int chan = CR_CHAN(insn->chanspec);
565 for (i = 0; i < insn->n; i++)
566 data[i] = devpriv->ao_readback[chan];
568 return i;
571 /* DIO devices are slightly special. Although it is possible to
572 * implement the insn_read/insn_write interface, it is much more
573 * useful to applications if you implement the insn_bits interface.
574 * This allows packed reading/writing of the DIO channels. The
575 * comedi core can convert between insn_bits and insn_read/write */
576 static int das16cs_dio_insn_bits(struct comedi_device *dev,
577 struct comedi_subdevice *s,
578 struct comedi_insn *insn, unsigned int *data)
580 if (insn->n != 2)
581 return -EINVAL;
583 if (data[0]) {
584 s->state &= ~data[0];
585 s->state |= data[0] & data[1];
587 outw(s->state, dev->iobase + 16);
590 /* on return, data[1] contains the value of the digital
591 * input and output lines. */
592 data[1] = inw(dev->iobase + 16);
594 return 2;
597 static int das16cs_dio_insn_config(struct comedi_device *dev,
598 struct comedi_subdevice *s,
599 struct comedi_insn *insn, unsigned int *data)
601 int chan = CR_CHAN(insn->chanspec);
602 int bits;
604 if (chan < 4)
605 bits = 0x0f;
606 else
607 bits = 0xf0;
609 switch (data[0]) {
610 case INSN_CONFIG_DIO_OUTPUT:
611 s->io_bits |= bits;
612 break;
613 case INSN_CONFIG_DIO_INPUT:
614 s->io_bits &= bits;
615 break;
616 case INSN_CONFIG_DIO_QUERY:
617 data[1] =
618 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
619 return insn->n;
620 break;
621 default:
622 return -EINVAL;
623 break;
626 devpriv->status2 &= ~0x00c0;
627 devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
628 devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
630 outw(devpriv->status2, dev->iobase + 6);
632 return insn->n;
635 static int das16cs_timer_insn_read(struct comedi_device *dev,
636 struct comedi_subdevice *s,
637 struct comedi_insn *insn, unsigned int *data)
639 return -EINVAL;
642 static int das16cs_timer_insn_config(struct comedi_device *dev,
643 struct comedi_subdevice *s,
644 struct comedi_insn *insn,
645 unsigned int *data)
647 return -EINVAL;
650 /* PCMCIA stuff */
652 /*======================================================================
654 The following pcmcia code for the pcm-das08 is adapted from the
655 dummy_cs.c driver of the Linux PCMCIA Card Services package.
657 The initial developer of the original code is David A. Hinds
658 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
659 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
661 ======================================================================*/
664 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
665 you do not define PCMCIA_DEBUG at all, all the debug code will be
666 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
667 be present but disabled -- but it can then be enabled for specific
668 modules at load time with a 'pc_debug=#' option to insmod.
670 #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
672 #ifdef PCMCIA_DEBUG
673 static int pc_debug = PCMCIA_DEBUG;
674 module_param(pc_debug, int, 0644);
675 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
676 static char *version =
677 "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
678 #else
679 #define DEBUG(n, args...)
680 #endif
682 /*====================================================================*/
684 static void das16cs_pcmcia_config(struct pcmcia_device *link);
685 static void das16cs_pcmcia_release(struct pcmcia_device *link);
686 static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
687 static int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
690 The attach() and detach() entry points are used to create and destroy
691 "instances" of the driver, where each instance represents everything
692 needed to manage one actual PCMCIA card.
695 static int das16cs_pcmcia_attach(struct pcmcia_device *);
696 static void das16cs_pcmcia_detach(struct pcmcia_device *);
699 You'll also need to prototype all the functions that will actually
700 be used to talk to your device. See 'memory_cs' for a good example
701 of a fully self-sufficient driver; the other drivers rely more or
702 less on other parts of the kernel.
706 The dev_info variable is the "key" that is used to match up this
707 device driver with appropriate cards, through the card configuration
708 database.
711 static dev_info_t dev_info = "cb_das16_cs";
713 struct local_info_t {
714 struct pcmcia_device *link;
715 dev_node_t node;
716 int stop;
717 struct bus_operations *bus;
720 /*======================================================================
722 das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
723 local data structures for one device. The device is registered
724 with Card Services.
726 The dev_link structure is initialized, but we don't actually
727 configure the card at this point -- we wait until we receive a
728 card insertion event.
730 ======================================================================*/
732 static int das16cs_pcmcia_attach(struct pcmcia_device *link)
734 struct local_info_t *local;
736 DEBUG(0, "das16cs_pcmcia_attach()\n");
738 /* Allocate space for private device-specific data */
739 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
740 if (!local)
741 return -ENOMEM;
742 local->link = link;
743 link->priv = local;
745 /* Initialize the pcmcia_device structure */
746 /* Interrupt setup */
747 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
748 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
749 link->irq.Handler = NULL;
751 link->conf.Attributes = 0;
752 link->conf.IntType = INT_MEMORY_AND_IO;
754 cur_dev = link;
756 das16cs_pcmcia_config(link);
758 return 0;
759 } /* das16cs_pcmcia_attach */
761 static void das16cs_pcmcia_detach(struct pcmcia_device *link)
763 DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link);
765 if (link->dev_node) {
766 ((struct local_info_t *)link->priv)->stop = 1;
767 das16cs_pcmcia_release(link);
769 /* This points to the parent struct local_info_t struct */
770 if (link->priv)
771 kfree(link->priv);
772 } /* das16cs_pcmcia_detach */
774 static void das16cs_pcmcia_config(struct pcmcia_device *link)
776 struct local_info_t *dev = link->priv;
777 tuple_t tuple;
778 cisparse_t parse;
779 int last_fn, last_ret;
780 u_char buf[64];
781 cistpl_cftable_entry_t dflt = { 0 };
783 DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link);
786 This reads the card's CONFIG tuple to find its configuration
787 registers.
789 tuple.DesiredTuple = CISTPL_CONFIG;
790 tuple.Attributes = 0;
791 tuple.TupleData = buf;
792 tuple.TupleDataMax = sizeof(buf);
793 tuple.TupleOffset = 0;
795 last_fn = GetFirstTuple;
796 last_ret = pcmcia_get_first_tuple(link, &tuple);
797 if (last_ret != 0)
798 goto cs_failed;
800 last_fn = GetTupleData;
801 last_ret = pcmcia_get_tuple_data(link, &tuple);
802 if (last_ret != 0)
803 goto cs_failed;
805 last_fn = ParseTuple;
806 last_ret = pcmcia_parse_tuple(&tuple, &parse);
807 if (last_ret != 0)
808 goto cs_failed;
810 link->conf.ConfigBase = parse.config.base;
811 link->conf.Present = parse.config.rmask[0];
814 In this loop, we scan the CIS for configuration table entries,
815 each of which describes a valid card configuration, including
816 voltage, IO window, memory window, and interrupt settings.
818 We make no assumptions about the card to be configured: we use
819 just the information available in the CIS. In an ideal world,
820 this would work for any PCMCIA card, but it requires a complete
821 and accurate CIS. In practice, a driver usually "knows" most of
822 these things without consulting the CIS, and most client drivers
823 will only use the CIS to fill in implementation-defined details.
825 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
826 last_fn = GetFirstTuple;
828 last_ret = pcmcia_get_first_tuple(link, &tuple);
829 if (last_ret)
830 goto cs_failed;
832 while (1) {
833 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
834 if (pcmcia_get_tuple_data(link, &tuple))
835 goto next_entry;
836 if (pcmcia_parse_tuple(&tuple, &parse))
837 goto next_entry;
839 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
840 dflt = *cfg;
841 if (cfg->index == 0)
842 goto next_entry;
843 link->conf.ConfigIndex = cfg->index;
845 /* Does this card need audio output? */
846 /* if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
847 link->conf.Attributes |= CONF_ENABLE_SPKR;
848 link->conf.Status = CCSR_AUDIO_ENA;
851 /* Do we need to allocate an interrupt? */
852 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
853 link->conf.Attributes |= CONF_ENABLE_IRQ;
855 /* IO window settings */
856 link->io.NumPorts1 = link->io.NumPorts2 = 0;
857 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
858 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
859 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
860 if (!(io->flags & CISTPL_IO_8BIT))
861 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
862 if (!(io->flags & CISTPL_IO_16BIT))
863 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
864 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
865 link->io.BasePort1 = io->win[0].base;
866 link->io.NumPorts1 = io->win[0].len;
867 if (io->nwin > 1) {
868 link->io.Attributes2 = link->io.Attributes1;
869 link->io.BasePort2 = io->win[1].base;
870 link->io.NumPorts2 = io->win[1].len;
872 /* This reserves IO space but doesn't actually enable it */
873 if (pcmcia_request_io(link, &link->io))
874 goto next_entry;
877 /* If we got this far, we're cool! */
878 break;
880 next_entry:
881 last_fn = GetNextTuple;
883 last_ret = pcmcia_get_next_tuple(link, &tuple);
884 if (last_ret)
885 goto cs_failed;
889 Allocate an interrupt line. Note that this does not assign a
890 handler to the interrupt, unless the 'Handler' member of the
891 irq structure is initialized.
893 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
894 last_fn = RequestIRQ;
896 last_ret = pcmcia_request_irq(link, &link->irq);
897 if (last_ret)
898 goto cs_failed;
901 This actually configures the PCMCIA socket -- setting up
902 the I/O windows and the interrupt mapping, and putting the
903 card and host interface into "Memory and IO" mode.
905 last_fn = RequestConfiguration;
906 last_ret = pcmcia_request_configuration(link, &link->conf);
907 if (last_ret)
908 goto cs_failed;
911 At this point, the dev_node_t structure(s) need to be
912 initialized and arranged in a linked list at link->dev.
914 sprintf(dev->node.dev_name, "cb_das16_cs");
915 dev->node.major = dev->node.minor = 0;
916 link->dev_node = &dev->node;
918 /* Finally, report what we've done */
919 printk(KERN_INFO "%s: index 0x%02x",
920 dev->node.dev_name, link->conf.ConfigIndex);
921 if (link->conf.Attributes & CONF_ENABLE_IRQ)
922 printk(", irq %u", link->irq.AssignedIRQ);
923 if (link->io.NumPorts1)
924 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
925 link->io.BasePort1 + link->io.NumPorts1 - 1);
926 if (link->io.NumPorts2)
927 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
928 link->io.BasePort2 + link->io.NumPorts2 - 1);
929 printk("\n");
931 return;
933 cs_failed:
934 cs_error(link, last_fn, last_ret);
935 das16cs_pcmcia_release(link);
936 } /* das16cs_pcmcia_config */
938 static void das16cs_pcmcia_release(struct pcmcia_device *link)
940 DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
941 pcmcia_disable_device(link);
942 } /* das16cs_pcmcia_release */
944 static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
946 struct local_info_t *local = link->priv;
948 /* Mark the device as stopped, to block IO until later */
949 local->stop = 1;
951 return 0;
952 } /* das16cs_pcmcia_suspend */
954 static int das16cs_pcmcia_resume(struct pcmcia_device *link)
956 struct local_info_t *local = link->priv;
958 local->stop = 0;
959 return 0;
960 } /* das16cs_pcmcia_resume */
962 /*====================================================================*/
964 static struct pcmcia_device_id das16cs_id_table[] = {
965 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
966 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
967 PCMCIA_DEVICE_NULL
970 MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
972 struct pcmcia_driver das16cs_driver = {
973 .probe = das16cs_pcmcia_attach,
974 .remove = das16cs_pcmcia_detach,
975 .suspend = das16cs_pcmcia_suspend,
976 .resume = das16cs_pcmcia_resume,
977 .id_table = das16cs_id_table,
978 .owner = THIS_MODULE,
979 .drv = {
980 .name = dev_info,
984 static int __init init_das16cs_pcmcia_cs(void)
986 DEBUG(0, "%s\n", version);
987 pcmcia_register_driver(&das16cs_driver);
988 return 0;
991 static void __exit exit_das16cs_pcmcia_cs(void)
993 DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
994 pcmcia_unregister_driver(&das16cs_driver);
997 int __init init_module(void)
999 int ret;
1001 ret = init_das16cs_pcmcia_cs();
1002 if (ret < 0)
1003 return ret;
1005 return comedi_driver_register(&driver_das16cs);
1008 void __exit cleanup_module(void)
1010 exit_das16cs_pcmcia_cs();
1011 comedi_driver_unregister(&driver_das16cs);
1014 #else
1015 COMEDI_INITCLEANUP(driver_das16cs);
1016 #endif /* CONFIG_PCMCIA */