Staging: comedi: remove comedi-specific wrappers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / comedi / drivers / cb_das16_cs.c
blob7b064d5df6ff5918c5c2918cf00664357ee37f57
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 "../comedidev.h"
35 #include <linux/delay.h>
36 #include <linux/pci.h>
38 #include <pcmcia/cs_types.h>
39 #include <pcmcia/cs.h>
40 #include <pcmcia/cistpl.h>
41 #include <pcmcia/ds.h>
43 #include "8253.h"
45 #define DAS16CS_SIZE 18
47 #define DAS16CS_ADC_DATA 0
48 #define DAS16CS_DIO_MUX 2
49 #define DAS16CS_MISC1 4
50 #define DAS16CS_MISC2 6
51 #define DAS16CS_CTR0 8
52 #define DAS16CS_CTR1 10
53 #define DAS16CS_CTR2 12
54 #define DAS16CS_CTR_CONTROL 14
55 #define DAS16CS_DIO 16
57 struct das16cs_board {
58 const char *name;
59 int device_id;
60 int n_ao_chans;
62 static const struct das16cs_board das16cs_boards[] = {
64 .device_id = 0x0000,/* unknown */
65 .name = "PC-CARD DAS16/16",
66 .n_ao_chans = 0,
69 .device_id = 0x0039,
70 .name = "PC-CARD DAS16/16-AO",
71 .n_ao_chans = 2,
74 .device_id = 0x4009,
75 .name = "PCM-DAS16s/16",
76 .n_ao_chans = 0,
80 #define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
81 #define thisboard ((const struct das16cs_board *)dev->board_ptr)
83 struct das16cs_private {
84 struct pcmcia_device *link;
86 unsigned int ao_readback[2];
87 unsigned short status1;
88 unsigned short status2;
90 #define devpriv ((struct das16cs_private *)dev->private)
92 static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
93 static int das16cs_detach(struct comedi_device *dev);
94 static struct comedi_driver driver_das16cs = {
95 .driver_name = "cb_das16_cs",
96 .module = THIS_MODULE,
97 .attach = das16cs_attach,
98 .detach = das16cs_detach,
101 static struct pcmcia_device *cur_dev = NULL;
103 static const struct comedi_lrange das16cs_ai_range = { 4, {
104 RANGE(-10, 10),
105 RANGE(-5, 5),
106 RANGE(-2.5, 2.5),
107 RANGE(-1.25, 1.25),
111 static irqreturn_t das16cs_interrupt(int irq, void *d);
112 static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
113 struct comedi_insn *insn, unsigned int *data);
114 static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
115 static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
116 struct comedi_cmd *cmd);
117 static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
118 struct comedi_insn *insn, unsigned int *data);
119 static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
120 struct comedi_insn *insn, unsigned int *data);
121 static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
122 struct comedi_insn *insn, unsigned int *data);
123 static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
124 struct comedi_insn *insn, unsigned int *data);
125 static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
126 struct comedi_insn *insn, unsigned int *data);
127 static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
128 struct comedi_insn *insn, unsigned int *data);
130 static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link)
132 tuple_t tuple;
133 u_short buf[128];
134 int prodid = 0;
136 tuple.TupleData = (cisdata_t *) buf;
137 tuple.TupleOffset = 0;
138 tuple.TupleDataMax = 255;
139 tuple.DesiredTuple = CISTPL_MANFID;
140 tuple.Attributes = TUPLE_RETURN_COMMON;
141 if ((pcmcia_get_first_tuple(link, &tuple) == 0) &&
142 (pcmcia_get_tuple_data(link, &tuple) == 0)) {
143 prodid = le16_to_cpu(buf[1]);
146 return prodid;
149 static const struct das16cs_board *das16cs_probe(struct comedi_device * dev,
150 struct pcmcia_device *link)
152 int id;
153 int i;
155 id = get_prodid(dev, link);
157 for (i = 0; i < n_boards; i++) {
158 if (das16cs_boards[i].device_id == id) {
159 return das16cs_boards + i;
163 printk("unknown board!\n");
165 return NULL;
168 static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
170 struct pcmcia_device *link;
171 struct comedi_subdevice *s;
172 int ret;
173 int i;
175 printk("comedi%d: cb_das16_cs: ", dev->minor);
177 link = cur_dev; /* XXX hack */
178 if (!link)
179 return -EIO;
181 dev->iobase = link->io.BasePort1;
182 printk("I/O base=0x%04lx ", dev->iobase);
184 printk("fingerprint:\n");
185 for (i = 0; i < 48; i += 2) {
186 printk("%04x ", inw(dev->iobase + i));
188 printk("\n");
190 ret = request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
191 IRQF_SHARED, "cb_das16_cs", dev);
192 if (ret < 0) {
193 return ret;
195 dev->irq = link->irq.AssignedIRQ;
196 printk("irq=%u ", dev->irq);
198 dev->board_ptr = das16cs_probe(dev, link);
199 if (!dev->board_ptr)
200 return -EIO;
202 dev->board_name = thisboard->name;
204 if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
205 return -ENOMEM;
207 if (alloc_subdevices(dev, 4) < 0)
208 return -ENOMEM;
210 s = dev->subdevices + 0;
211 dev->read_subdev = s;
212 /* analog input subdevice */
213 s->type = COMEDI_SUBD_AI;
214 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
215 s->n_chan = 16;
216 s->maxdata = 0xffff;
217 s->range_table = &das16cs_ai_range;
218 s->len_chanlist = 16;
219 s->insn_read = das16cs_ai_rinsn;
220 s->do_cmd = das16cs_ai_cmd;
221 s->do_cmdtest = das16cs_ai_cmdtest;
223 s = dev->subdevices + 1;
224 /* analog output subdevice */
225 if (thisboard->n_ao_chans) {
226 s->type = COMEDI_SUBD_AO;
227 s->subdev_flags = SDF_WRITABLE;
228 s->n_chan = thisboard->n_ao_chans;
229 s->maxdata = 0xffff;
230 s->range_table = &range_bipolar10;
231 s->insn_write = &das16cs_ao_winsn;
232 s->insn_read = &das16cs_ao_rinsn;
235 s = dev->subdevices + 2;
236 /* digital i/o subdevice */
237 if (1) {
238 s->type = COMEDI_SUBD_DIO;
239 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
240 s->n_chan = 8;
241 s->maxdata = 1;
242 s->range_table = &range_digital;
243 s->insn_bits = das16cs_dio_insn_bits;
244 s->insn_config = das16cs_dio_insn_config;
245 } else {
246 s->type = COMEDI_SUBD_UNUSED;
249 s = dev->subdevices + 3;
250 /* timer subdevice */
251 if (0) {
252 s->type = COMEDI_SUBD_TIMER;
253 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
254 s->n_chan = 1;
255 s->maxdata = 0xff;
256 s->range_table = &range_unknown;
257 s->insn_read = das16cs_timer_insn_read;
258 s->insn_config = das16cs_timer_insn_config;
259 } else {
260 s->type = COMEDI_SUBD_UNUSED;
263 printk("attached\n");
265 return 1;
268 static int das16cs_detach(struct comedi_device *dev)
270 printk("comedi%d: das16cs: remove\n", dev->minor);
272 if (dev->irq) {
273 free_irq(dev->irq, dev);
276 return 0;
279 static irqreturn_t das16cs_interrupt(int irq, void *d)
281 /* struct comedi_device *dev = d; */
282 return IRQ_HANDLED;
286 * "instructions" read/write data in "one-shot" or "software-triggered"
287 * mode.
289 static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
290 struct comedi_insn *insn, unsigned int *data)
292 int i;
293 int to;
294 int aref;
295 int range;
296 int chan;
297 static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
299 chan = CR_CHAN(insn->chanspec);
300 aref = CR_AREF(insn->chanspec);
301 range = CR_RANGE(insn->chanspec);
303 outw(chan, dev->iobase + 2);
305 devpriv->status1 &= ~0xf320;
306 devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
307 outw(devpriv->status1, dev->iobase + 4);
309 devpriv->status2 &= ~0xff00;
310 devpriv->status2 |= range_bits[range];
311 outw(devpriv->status2, dev->iobase + 6);
313 for (i = 0; i < insn->n; i++) {
314 outw(0, dev->iobase);
316 #define TIMEOUT 1000
317 for (to = 0; to < TIMEOUT; to++) {
318 if (inw(dev->iobase + 4) & 0x0080)
319 break;
321 if (to == TIMEOUT) {
322 printk("cb_das16_cs: ai timeout\n");
323 return -ETIME;
325 data[i] = (unsigned short)inw(dev->iobase + 0);
328 return i;
331 static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
333 return -EINVAL;
336 static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
337 struct comedi_cmd *cmd)
339 int err = 0;
340 int tmp;
342 /* cmdtest tests a particular command to see if it is valid.
343 * Using the cmdtest ioctl, a user can create a valid cmd
344 * and then have it executes by the cmd ioctl.
346 * cmdtest returns 1,2,3,4 or 0, depending on which tests
347 * the command passes. */
349 /* step 1: make sure trigger sources are trivially valid */
351 tmp = cmd->start_src;
352 cmd->start_src &= TRIG_NOW;
353 if (!cmd->start_src || tmp != cmd->start_src)
354 err++;
356 tmp = cmd->scan_begin_src;
357 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
358 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
359 err++;
361 tmp = cmd->convert_src;
362 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
363 if (!cmd->convert_src || tmp != cmd->convert_src)
364 err++;
366 tmp = cmd->scan_end_src;
367 cmd->scan_end_src &= TRIG_COUNT;
368 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
369 err++;
371 tmp = cmd->stop_src;
372 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
373 if (!cmd->stop_src || tmp != cmd->stop_src)
374 err++;
376 if (err)
377 return 1;
379 /* step 2: make sure trigger sources are unique and mutually compatible */
381 /* note that mutual compatiblity is not an issue here */
382 if (cmd->scan_begin_src != TRIG_TIMER &&
383 cmd->scan_begin_src != TRIG_EXT)
384 err++;
385 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
386 err++;
387 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
388 err++;
390 if (err)
391 return 2;
393 /* step 3: make sure arguments are trivially compatible */
395 if (cmd->start_arg != 0) {
396 cmd->start_arg = 0;
397 err++;
399 #define MAX_SPEED 10000 /* in nanoseconds */
400 #define MIN_SPEED 1000000000 /* in nanoseconds */
402 if (cmd->scan_begin_src == TRIG_TIMER) {
403 if (cmd->scan_begin_arg < MAX_SPEED) {
404 cmd->scan_begin_arg = MAX_SPEED;
405 err++;
407 if (cmd->scan_begin_arg > MIN_SPEED) {
408 cmd->scan_begin_arg = MIN_SPEED;
409 err++;
411 } else {
412 /* external trigger */
413 /* should be level/edge, hi/lo specification here */
414 /* should specify multiple external triggers */
415 if (cmd->scan_begin_arg > 9) {
416 cmd->scan_begin_arg = 9;
417 err++;
420 if (cmd->convert_src == TRIG_TIMER) {
421 if (cmd->convert_arg < MAX_SPEED) {
422 cmd->convert_arg = MAX_SPEED;
423 err++;
425 if (cmd->convert_arg > MIN_SPEED) {
426 cmd->convert_arg = MIN_SPEED;
427 err++;
429 } else {
430 /* external trigger */
431 /* see above */
432 if (cmd->convert_arg > 9) {
433 cmd->convert_arg = 9;
434 err++;
438 if (cmd->scan_end_arg != cmd->chanlist_len) {
439 cmd->scan_end_arg = cmd->chanlist_len;
440 err++;
442 if (cmd->stop_src == TRIG_COUNT) {
443 if (cmd->stop_arg > 0x00ffffff) {
444 cmd->stop_arg = 0x00ffffff;
445 err++;
447 } else {
448 /* TRIG_NONE */
449 if (cmd->stop_arg != 0) {
450 cmd->stop_arg = 0;
451 err++;
455 if (err)
456 return 3;
458 /* step 4: fix up any arguments */
460 if (cmd->scan_begin_src == TRIG_TIMER) {
461 unsigned int div1, div2;
463 tmp = cmd->scan_begin_arg;
464 i8253_cascade_ns_to_timer(100, &div1, &div2,
465 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
466 if (tmp != cmd->scan_begin_arg)
467 err++;
469 if (cmd->convert_src == TRIG_TIMER) {
470 unsigned int div1, div2;
472 tmp = cmd->convert_arg;
473 i8253_cascade_ns_to_timer(100, &div1, &div2,
474 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
475 if (tmp != cmd->convert_arg)
476 err++;
477 if (cmd->scan_begin_src == TRIG_TIMER &&
478 cmd->scan_begin_arg <
479 cmd->convert_arg * cmd->scan_end_arg) {
480 cmd->scan_begin_arg =
481 cmd->convert_arg * cmd->scan_end_arg;
482 err++;
486 if (err)
487 return 4;
489 return 0;
492 static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
493 struct comedi_insn *insn, unsigned int *data)
495 int i;
496 int chan = CR_CHAN(insn->chanspec);
497 unsigned short status1;
498 unsigned short d;
499 int bit;
501 for (i = 0; i < insn->n; i++) {
502 devpriv->ao_readback[chan] = data[i];
503 d = data[i];
505 outw(devpriv->status1, dev->iobase + 4);
506 udelay(1);
508 status1 = devpriv->status1 & ~0xf;
509 if (chan)
510 status1 |= 0x0001;
511 else
512 status1 |= 0x0008;
514 /* printk("0x%04x\n",status1);*/
515 outw(status1, dev->iobase + 4);
516 udelay(1);
518 for (bit = 15; bit >= 0; bit--) {
519 int b = (d >> bit) & 0x1;
520 b <<= 1;
521 /* printk("0x%04x\n",status1 | b | 0x0000);*/
522 outw(status1 | b | 0x0000, dev->iobase + 4);
523 udelay(1);
524 /* printk("0x%04x\n",status1 | b | 0x0004);*/
525 outw(status1 | b | 0x0004, dev->iobase + 4);
526 udelay(1);
528 /* make high both DAC0CS and DAC1CS to load
529 new data and update analog output*/
530 outw(status1 | 0x9, dev->iobase + 4);
533 return i;
536 /* AO subdevices should have a read insn as well as a write insn.
537 * Usually this means copying a value stored in devpriv. */
538 static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
539 struct comedi_insn *insn, unsigned int *data)
541 int i;
542 int chan = CR_CHAN(insn->chanspec);
544 for (i = 0; i < insn->n; i++)
545 data[i] = devpriv->ao_readback[chan];
547 return i;
550 /* DIO devices are slightly special. Although it is possible to
551 * implement the insn_read/insn_write interface, it is much more
552 * useful to applications if you implement the insn_bits interface.
553 * This allows packed reading/writing of the DIO channels. The
554 * comedi core can convert between insn_bits and insn_read/write */
555 static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
556 struct comedi_insn *insn, unsigned int *data)
558 if (insn->n != 2)
559 return -EINVAL;
561 if (data[0]) {
562 s->state &= ~data[0];
563 s->state |= data[0] & data[1];
565 outw(s->state, dev->iobase + 16);
568 /* on return, data[1] contains the value of the digital
569 * input and output lines. */
570 data[1] = inw(dev->iobase + 16);
572 return 2;
575 static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
576 struct comedi_insn *insn, unsigned int *data)
578 int chan = CR_CHAN(insn->chanspec);
579 int bits;
581 if (chan < 4)
582 bits = 0x0f;
583 else
584 bits = 0xf0;
586 switch (data[0]) {
587 case INSN_CONFIG_DIO_OUTPUT:
588 s->io_bits |= bits;
589 break;
590 case INSN_CONFIG_DIO_INPUT:
591 s->io_bits &= bits;
592 break;
593 case INSN_CONFIG_DIO_QUERY:
594 data[1] =
595 (s->
596 io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
597 return insn->n;
598 break;
599 default:
600 return -EINVAL;
601 break;
604 devpriv->status2 &= ~0x00c0;
605 devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
606 devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
608 outw(devpriv->status2, dev->iobase + 6);
610 return insn->n;
613 static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
614 struct comedi_insn *insn, unsigned int *data)
616 return -EINVAL;
619 static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
620 struct comedi_insn *insn, unsigned int *data)
622 return -EINVAL;
625 /* PCMCIA stuff */
627 /*======================================================================
629 The following pcmcia code for the pcm-das08 is adapted from the
630 dummy_cs.c driver of the Linux PCMCIA Card Services package.
632 The initial developer of the original code is David A. Hinds
633 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
634 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
636 ======================================================================*/
639 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
640 you do not define PCMCIA_DEBUG at all, all the debug code will be
641 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
642 be present but disabled -- but it can then be enabled for specific
643 modules at load time with a 'pc_debug=#' option to insmod.
645 #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
647 #ifdef PCMCIA_DEBUG
648 static int pc_debug = PCMCIA_DEBUG;
649 module_param(pc_debug, int, 0644);
650 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
651 static char *version =
652 "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
653 #else
654 #define DEBUG(n, args...)
655 #endif
657 /*====================================================================*/
659 static void das16cs_pcmcia_config(struct pcmcia_device *link);
660 static void das16cs_pcmcia_release(struct pcmcia_device *link);
661 static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
662 static int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
665 The attach() and detach() entry points are used to create and destroy
666 "instances" of the driver, where each instance represents everything
667 needed to manage one actual PCMCIA card.
670 static int das16cs_pcmcia_attach(struct pcmcia_device *);
671 static void das16cs_pcmcia_detach(struct pcmcia_device *);
674 You'll also need to prototype all the functions that will actually
675 be used to talk to your device. See 'memory_cs' for a good example
676 of a fully self-sufficient driver; the other drivers rely more or
677 less on other parts of the kernel.
681 The dev_info variable is the "key" that is used to match up this
682 device driver with appropriate cards, through the card configuration
683 database.
686 static dev_info_t dev_info = "cb_das16_cs";
688 struct local_info_t {
689 struct pcmcia_device *link;
690 dev_node_t node;
691 int stop;
692 struct bus_operations *bus;
695 /*======================================================================
697 das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
698 local data structures for one device. The device is registered
699 with Card Services.
701 The dev_link structure is initialized, but we don't actually
702 configure the card at this point -- we wait until we receive a
703 card insertion event.
705 ======================================================================*/
707 static int das16cs_pcmcia_attach(struct pcmcia_device *link)
709 struct local_info_t *local;
711 DEBUG(0, "das16cs_pcmcia_attach()\n");
713 /* Allocate space for private device-specific data */
714 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
715 if (!local)
716 return -ENOMEM;
717 local->link = link;
718 link->priv = local;
720 /* Initialize the pcmcia_device structure */
721 /* Interrupt setup */
722 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
723 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
724 link->irq.Handler = NULL;
726 link->conf.Attributes = 0;
727 link->conf.IntType = INT_MEMORY_AND_IO;
729 cur_dev = link;
731 das16cs_pcmcia_config(link);
733 return 0;
734 } /* das16cs_pcmcia_attach */
736 static void das16cs_pcmcia_detach(struct pcmcia_device *link)
738 DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link);
740 if (link->dev_node) {
741 ((struct local_info_t *) link->priv)->stop = 1;
742 das16cs_pcmcia_release(link);
744 /* This points to the parent struct local_info_t struct */
745 if (link->priv)
746 kfree(link->priv);
747 } /* das16cs_pcmcia_detach */
749 static void das16cs_pcmcia_config(struct pcmcia_device *link)
751 struct local_info_t *dev = link->priv;
752 tuple_t tuple;
753 cisparse_t parse;
754 int last_fn, last_ret;
755 u_char buf[64];
756 cistpl_cftable_entry_t dflt = { 0 };
758 DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link);
761 This reads the card's CONFIG tuple to find its configuration
762 registers.
764 tuple.DesiredTuple = CISTPL_CONFIG;
765 tuple.Attributes = 0;
766 tuple.TupleData = buf;
767 tuple.TupleDataMax = sizeof(buf);
768 tuple.TupleOffset = 0;
770 last_fn = GetFirstTuple;
771 last_ret = pcmcia_get_first_tuple(link, &tuple);
772 if (last_ret != 0)
773 goto cs_failed;
775 last_fn = GetTupleData;
776 last_ret = pcmcia_get_tuple_data(link, &tuple);
777 if (last_ret != 0)
778 goto cs_failed;
780 last_fn = ParseTuple;
781 last_ret = pcmcia_parse_tuple(&tuple, &parse);
782 if (last_ret != 0)
783 goto cs_failed;
785 link->conf.ConfigBase = parse.config.base;
786 link->conf.Present = parse.config.rmask[0];
789 In this loop, we scan the CIS for configuration table entries,
790 each of which describes a valid card configuration, including
791 voltage, IO window, memory window, and interrupt settings.
793 We make no assumptions about the card to be configured: we use
794 just the information available in the CIS. In an ideal world,
795 this would work for any PCMCIA card, but it requires a complete
796 and accurate CIS. In practice, a driver usually "knows" most of
797 these things without consulting the CIS, and most client drivers
798 will only use the CIS to fill in implementation-defined details.
800 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
801 last_fn = GetFirstTuple;
803 last_ret = pcmcia_get_first_tuple(link, &tuple);
804 if (last_ret)
805 goto cs_failed;
807 while (1) {
808 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
809 if (pcmcia_get_tuple_data(link, &tuple))
810 goto next_entry;
811 if (pcmcia_parse_tuple(&tuple, &parse))
812 goto next_entry;
814 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
815 dflt = *cfg;
816 if (cfg->index == 0)
817 goto next_entry;
818 link->conf.ConfigIndex = cfg->index;
820 /* Does this card need audio output? */
821 /* if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
822 link->conf.Attributes |= CONF_ENABLE_SPKR;
823 link->conf.Status = CCSR_AUDIO_ENA;
826 /* Do we need to allocate an interrupt? */
827 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
828 link->conf.Attributes |= CONF_ENABLE_IRQ;
830 /* IO window settings */
831 link->io.NumPorts1 = link->io.NumPorts2 = 0;
832 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
833 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
834 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
835 if (!(io->flags & CISTPL_IO_8BIT))
836 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
837 if (!(io->flags & CISTPL_IO_16BIT))
838 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
839 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
840 link->io.BasePort1 = io->win[0].base;
841 link->io.NumPorts1 = io->win[0].len;
842 if (io->nwin > 1) {
843 link->io.Attributes2 = link->io.Attributes1;
844 link->io.BasePort2 = io->win[1].base;
845 link->io.NumPorts2 = io->win[1].len;
847 /* This reserves IO space but doesn't actually enable it */
848 if (pcmcia_request_io(link, &link->io))
849 goto next_entry;
852 /* If we got this far, we're cool! */
853 break;
855 next_entry:
856 last_fn = GetNextTuple;
858 last_ret = pcmcia_get_next_tuple(link, &tuple);
859 if (last_ret)
860 goto cs_failed;
864 Allocate an interrupt line. Note that this does not assign a
865 handler to the interrupt, unless the 'Handler' member of the
866 irq structure is initialized.
868 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
869 last_fn = RequestIRQ;
871 last_ret = pcmcia_request_irq(link, &link->irq);
872 if (last_ret)
873 goto cs_failed;
876 This actually configures the PCMCIA socket -- setting up
877 the I/O windows and the interrupt mapping, and putting the
878 card and host interface into "Memory and IO" mode.
880 last_fn = RequestConfiguration;
881 last_ret = pcmcia_request_configuration(link, &link->conf);
882 if (last_ret)
883 goto cs_failed;
886 At this point, the dev_node_t structure(s) need to be
887 initialized and arranged in a linked list at link->dev.
889 sprintf(dev->node.dev_name, "cb_das16_cs");
890 dev->node.major = dev->node.minor = 0;
891 link->dev_node = &dev->node;
893 /* Finally, report what we've done */
894 printk(KERN_INFO "%s: index 0x%02x",
895 dev->node.dev_name, link->conf.ConfigIndex);
896 if (link->conf.Attributes & CONF_ENABLE_IRQ)
897 printk(", irq %u", link->irq.AssignedIRQ);
898 if (link->io.NumPorts1)
899 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
900 link->io.BasePort1 + link->io.NumPorts1 - 1);
901 if (link->io.NumPorts2)
902 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
903 link->io.BasePort2 + link->io.NumPorts2 - 1);
904 printk("\n");
906 return;
908 cs_failed:
909 cs_error(link, last_fn, last_ret);
910 das16cs_pcmcia_release(link);
911 } /* das16cs_pcmcia_config */
913 static void das16cs_pcmcia_release(struct pcmcia_device *link)
915 DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
916 pcmcia_disable_device(link);
917 } /* das16cs_pcmcia_release */
919 static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
921 struct local_info_t *local = link->priv;
923 /* Mark the device as stopped, to block IO until later */
924 local->stop = 1;
926 return 0;
927 } /* das16cs_pcmcia_suspend */
929 static int das16cs_pcmcia_resume(struct pcmcia_device *link)
931 struct local_info_t *local = link->priv;
933 local->stop = 0;
934 return 0;
935 } /* das16cs_pcmcia_resume */
937 /*====================================================================*/
939 static struct pcmcia_device_id das16cs_id_table[] = {
940 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
941 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
942 PCMCIA_DEVICE_NULL
945 MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
947 struct pcmcia_driver das16cs_driver = {
948 .probe = das16cs_pcmcia_attach,
949 .remove = das16cs_pcmcia_detach,
950 .suspend = das16cs_pcmcia_suspend,
951 .resume = das16cs_pcmcia_resume,
952 .id_table = das16cs_id_table,
953 .owner = THIS_MODULE,
954 .drv = {
955 .name = dev_info,
959 static int __init init_das16cs_pcmcia_cs(void)
961 DEBUG(0, "%s\n", version);
962 pcmcia_register_driver(&das16cs_driver);
963 return 0;
966 static void __exit exit_das16cs_pcmcia_cs(void)
968 DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
969 pcmcia_unregister_driver(&das16cs_driver);
972 int __init init_module(void)
974 int ret;
976 ret = init_das16cs_pcmcia_cs();
977 if (ret < 0)
978 return ret;
980 return comedi_driver_register(&driver_das16cs);
983 void __exit cleanup_module(void)
985 exit_das16cs_pcmcia_cs();
986 comedi_driver_unregister(&driver_das16cs);
989 #else
990 COMEDI_INITCLEANUP(driver_das16cs);
991 #endif /* CONFIG_PCMCIA */