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.
25 Description: Computer Boards PC-CARD DAS16/16
26 Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO
28 Updated: Mon, 04 Nov 2002 20:04:21 -0800
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>
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 {
63 static const struct das16cs_board das16cs_boards[] = {
65 .device_id = 0x0000,/* unknown */
66 .name = "PC-CARD DAS16/16",
71 .name = "PC-CARD DAS16/16-AO",
76 .name = "PCM-DAS16s/16",
81 #define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
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, struct comedi_devconfig *it);
94 static int das16cs_detach(struct comedi_device *dev);
95 static struct comedi_driver driver_das16cs = {
96 .driver_name = "cb_das16_cs",
97 .module = THIS_MODULE,
98 .attach = das16cs_attach,
99 .detach = das16cs_detach,
102 static struct pcmcia_device *cur_dev = NULL;
104 static const struct comedi_lrange das16cs_ai_range = { 4, {
112 static irqreturn_t das16cs_interrupt(int irq, void *d);
113 static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
114 struct comedi_insn *insn, unsigned int *data);
115 static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
116 static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
117 struct comedi_cmd *cmd);
118 static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
119 struct comedi_insn *insn, unsigned int *data);
120 static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
121 struct comedi_insn *insn, unsigned int *data);
122 static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
123 struct comedi_insn *insn, unsigned int *data);
124 static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
125 struct comedi_insn *insn, unsigned int *data);
126 static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
127 struct comedi_insn *insn, unsigned int *data);
128 static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
129 struct comedi_insn *insn, unsigned int *data);
131 static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link)
137 tuple.TupleData = (cisdata_t *) buf;
138 tuple.TupleOffset = 0;
139 tuple.TupleDataMax = 255;
140 tuple.DesiredTuple = CISTPL_MANFID;
141 tuple.Attributes = TUPLE_RETURN_COMMON;
142 if ((pcmcia_get_first_tuple(link, &tuple) == 0) &&
143 (pcmcia_get_tuple_data(link, &tuple) == 0)) {
144 prodid = le16_to_cpu(buf[1]);
150 static const struct das16cs_board *das16cs_probe(struct comedi_device * dev,
151 struct pcmcia_device *link)
156 id = get_prodid(dev, link);
158 for (i = 0; i < n_boards; i++) {
159 if (das16cs_boards[i].device_id == id) {
160 return das16cs_boards + i;
164 printk("unknown board!\n");
169 static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
171 struct pcmcia_device *link;
172 struct comedi_subdevice *s;
176 printk("comedi%d: cb_das16_cs: ", dev->minor);
178 link = cur_dev; /* XXX hack */
182 dev->iobase = link->io.BasePort1;
183 printk("I/O base=0x%04lx ", dev->iobase);
185 printk("fingerprint:\n");
186 for (i = 0; i < 48; i += 2) {
187 printk("%04x ", inw(dev->iobase + i));
191 ret = request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
192 IRQF_SHARED, "cb_das16_cs", dev);
196 dev->irq = link->irq.AssignedIRQ;
197 printk("irq=%u ", dev->irq);
199 dev->board_ptr = das16cs_probe(dev, link);
203 dev->board_name = thisboard->name;
205 if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
208 if (alloc_subdevices(dev, 4) < 0)
211 s = dev->subdevices + 0;
212 dev->read_subdev = s;
213 /* analog input subdevice */
214 s->type = COMEDI_SUBD_AI;
215 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
218 s->range_table = &das16cs_ai_range;
219 s->len_chanlist = 16;
220 s->insn_read = das16cs_ai_rinsn;
221 s->do_cmd = das16cs_ai_cmd;
222 s->do_cmdtest = das16cs_ai_cmdtest;
224 s = dev->subdevices + 1;
225 /* analog output subdevice */
226 if (thisboard->n_ao_chans) {
227 s->type = COMEDI_SUBD_AO;
228 s->subdev_flags = SDF_WRITABLE;
229 s->n_chan = thisboard->n_ao_chans;
231 s->range_table = &range_bipolar10;
232 s->insn_write = &das16cs_ao_winsn;
233 s->insn_read = &das16cs_ao_rinsn;
236 s = dev->subdevices + 2;
237 /* digital i/o subdevice */
239 s->type = COMEDI_SUBD_DIO;
240 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
243 s->range_table = &range_digital;
244 s->insn_bits = das16cs_dio_insn_bits;
245 s->insn_config = das16cs_dio_insn_config;
247 s->type = COMEDI_SUBD_UNUSED;
250 s = dev->subdevices + 3;
251 /* timer subdevice */
253 s->type = COMEDI_SUBD_TIMER;
254 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
257 s->range_table = &range_unknown;
258 s->insn_read = das16cs_timer_insn_read;
259 s->insn_config = das16cs_timer_insn_config;
261 s->type = COMEDI_SUBD_UNUSED;
264 printk("attached\n");
269 static int das16cs_detach(struct comedi_device *dev)
271 printk("comedi%d: das16cs: remove\n", dev->minor);
274 free_irq(dev->irq, dev);
280 static irqreturn_t das16cs_interrupt(int irq, void *d)
282 /* struct comedi_device *dev = d; */
287 * "instructions" read/write data in "one-shot" or "software-triggered"
290 static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
291 struct comedi_insn *insn, unsigned int *data)
298 static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
300 chan = CR_CHAN(insn->chanspec);
301 aref = CR_AREF(insn->chanspec);
302 range = CR_RANGE(insn->chanspec);
304 outw(chan, dev->iobase + 2);
306 devpriv->status1 &= ~0xf320;
307 devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
308 outw(devpriv->status1, dev->iobase + 4);
310 devpriv->status2 &= ~0xff00;
311 devpriv->status2 |= range_bits[range];
312 outw(devpriv->status2, dev->iobase + 6);
314 for (i = 0; i < insn->n; i++) {
315 outw(0, dev->iobase);
318 for (to = 0; to < TIMEOUT; to++) {
319 if (inw(dev->iobase + 4) & 0x0080)
323 printk("cb_das16_cs: ai timeout\n");
326 data[i] = (unsigned short)inw(dev->iobase + 0);
332 static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
337 static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
338 struct comedi_cmd *cmd)
343 /* cmdtest tests a particular command to see if it is valid.
344 * Using the cmdtest ioctl, a user can create a valid cmd
345 * and then have it executes by the cmd ioctl.
347 * cmdtest returns 1,2,3,4 or 0, depending on which tests
348 * the command passes. */
350 /* step 1: make sure trigger sources are trivially valid */
352 tmp = cmd->start_src;
353 cmd->start_src &= TRIG_NOW;
354 if (!cmd->start_src || tmp != cmd->start_src)
357 tmp = cmd->scan_begin_src;
358 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
359 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
362 tmp = cmd->convert_src;
363 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
364 if (!cmd->convert_src || tmp != cmd->convert_src)
367 tmp = cmd->scan_end_src;
368 cmd->scan_end_src &= TRIG_COUNT;
369 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
373 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
374 if (!cmd->stop_src || tmp != cmd->stop_src)
380 /* step 2: make sure trigger sources are unique and mutually compatible */
382 /* note that mutual compatiblity is not an issue here */
383 if (cmd->scan_begin_src != TRIG_TIMER &&
384 cmd->scan_begin_src != TRIG_EXT)
386 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
388 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
394 /* step 3: make sure arguments are trivially compatible */
396 if (cmd->start_arg != 0) {
400 #define MAX_SPEED 10000 /* in nanoseconds */
401 #define MIN_SPEED 1000000000 /* in nanoseconds */
403 if (cmd->scan_begin_src == TRIG_TIMER) {
404 if (cmd->scan_begin_arg < MAX_SPEED) {
405 cmd->scan_begin_arg = MAX_SPEED;
408 if (cmd->scan_begin_arg > MIN_SPEED) {
409 cmd->scan_begin_arg = MIN_SPEED;
413 /* external trigger */
414 /* should be level/edge, hi/lo specification here */
415 /* should specify multiple external triggers */
416 if (cmd->scan_begin_arg > 9) {
417 cmd->scan_begin_arg = 9;
421 if (cmd->convert_src == TRIG_TIMER) {
422 if (cmd->convert_arg < MAX_SPEED) {
423 cmd->convert_arg = MAX_SPEED;
426 if (cmd->convert_arg > MIN_SPEED) {
427 cmd->convert_arg = MIN_SPEED;
431 /* external trigger */
433 if (cmd->convert_arg > 9) {
434 cmd->convert_arg = 9;
439 if (cmd->scan_end_arg != cmd->chanlist_len) {
440 cmd->scan_end_arg = cmd->chanlist_len;
443 if (cmd->stop_src == TRIG_COUNT) {
444 if (cmd->stop_arg > 0x00ffffff) {
445 cmd->stop_arg = 0x00ffffff;
450 if (cmd->stop_arg != 0) {
459 /* step 4: fix up any arguments */
461 if (cmd->scan_begin_src == TRIG_TIMER) {
462 unsigned int div1, div2;
464 tmp = cmd->scan_begin_arg;
465 i8253_cascade_ns_to_timer(100, &div1, &div2,
466 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
467 if (tmp != cmd->scan_begin_arg)
470 if (cmd->convert_src == TRIG_TIMER) {
471 unsigned int div1, div2;
473 tmp = cmd->convert_arg;
474 i8253_cascade_ns_to_timer(100, &div1, &div2,
475 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
476 if (tmp != cmd->convert_arg)
478 if (cmd->scan_begin_src == TRIG_TIMER &&
479 cmd->scan_begin_arg <
480 cmd->convert_arg * cmd->scan_end_arg) {
481 cmd->scan_begin_arg =
482 cmd->convert_arg * cmd->scan_end_arg;
493 static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
494 struct comedi_insn *insn, unsigned int *data)
497 int chan = CR_CHAN(insn->chanspec);
498 unsigned short status1;
502 for (i = 0; i < insn->n; i++) {
503 devpriv->ao_readback[chan] = data[i];
506 outw(devpriv->status1, dev->iobase + 4);
509 status1 = devpriv->status1 & ~0xf;
515 /* printk("0x%04x\n",status1);*/
516 outw(status1, dev->iobase + 4);
519 for (bit = 15; bit >= 0; bit--) {
520 int b = (d >> bit) & 0x1;
522 /* printk("0x%04x\n",status1 | b | 0x0000);*/
523 outw(status1 | b | 0x0000, dev->iobase + 4);
525 /* printk("0x%04x\n",status1 | b | 0x0004);*/
526 outw(status1 | b | 0x0004, dev->iobase + 4);
529 /* make high both DAC0CS and DAC1CS to load
530 new data and update analog output*/
531 outw(status1 | 0x9, dev->iobase + 4);
537 /* AO subdevices should have a read insn as well as a write insn.
538 * Usually this means copying a value stored in devpriv. */
539 static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
540 struct comedi_insn *insn, unsigned int *data)
543 int chan = CR_CHAN(insn->chanspec);
545 for (i = 0; i < insn->n; i++)
546 data[i] = devpriv->ao_readback[chan];
551 /* DIO devices are slightly special. Although it is possible to
552 * implement the insn_read/insn_write interface, it is much more
553 * useful to applications if you implement the insn_bits interface.
554 * This allows packed reading/writing of the DIO channels. The
555 * comedi core can convert between insn_bits and insn_read/write */
556 static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
557 struct comedi_insn *insn, unsigned int *data)
563 s->state &= ~data[0];
564 s->state |= data[0] & data[1];
566 outw(s->state, dev->iobase + 16);
569 /* on return, data[1] contains the value of the digital
570 * input and output lines. */
571 data[1] = inw(dev->iobase + 16);
576 static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
577 struct comedi_insn *insn, unsigned int *data)
579 int chan = CR_CHAN(insn->chanspec);
588 case INSN_CONFIG_DIO_OUTPUT:
591 case INSN_CONFIG_DIO_INPUT:
594 case INSN_CONFIG_DIO_QUERY:
597 io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
605 devpriv->status2 &= ~0x00c0;
606 devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
607 devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
609 outw(devpriv->status2, dev->iobase + 6);
614 static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
615 struct comedi_insn *insn, unsigned int *data)
620 static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
621 struct comedi_insn *insn, unsigned int *data)
628 /*======================================================================
630 The following pcmcia code for the pcm-das08 is adapted from the
631 dummy_cs.c driver of the Linux PCMCIA Card Services package.
633 The initial developer of the original code is David A. Hinds
634 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
635 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
637 ======================================================================*/
640 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
641 you do not define PCMCIA_DEBUG at all, all the debug code will be
642 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
643 be present but disabled -- but it can then be enabled for specific
644 modules at load time with a 'pc_debug=#' option to insmod.
646 #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
649 static int pc_debug = PCMCIA_DEBUG;
650 module_param(pc_debug, int, 0644);
651 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
652 static char *version =
653 "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
655 #define DEBUG(n, args...)
658 /*====================================================================*/
660 static void das16cs_pcmcia_config(struct pcmcia_device *link);
661 static void das16cs_pcmcia_release(struct pcmcia_device *link);
662 static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
663 static int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
666 The attach() and detach() entry points are used to create and destroy
667 "instances" of the driver, where each instance represents everything
668 needed to manage one actual PCMCIA card.
671 static int das16cs_pcmcia_attach(struct pcmcia_device *);
672 static void das16cs_pcmcia_detach(struct pcmcia_device *);
675 You'll also need to prototype all the functions that will actually
676 be used to talk to your device. See 'memory_cs' for a good example
677 of a fully self-sufficient driver; the other drivers rely more or
678 less on other parts of the kernel.
682 The dev_info variable is the "key" that is used to match up this
683 device driver with appropriate cards, through the card configuration
687 static dev_info_t dev_info = "cb_das16_cs";
689 struct local_info_t {
690 struct pcmcia_device *link;
693 struct bus_operations *bus;
696 /*======================================================================
698 das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
699 local data structures for one device. The device is registered
702 The dev_link structure is initialized, but we don't actually
703 configure the card at this point -- we wait until we receive a
704 card insertion event.
706 ======================================================================*/
708 static int das16cs_pcmcia_attach(struct pcmcia_device *link)
710 struct local_info_t *local;
712 DEBUG(0, "das16cs_pcmcia_attach()\n");
714 /* Allocate space for private device-specific data */
715 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
721 /* Initialize the pcmcia_device structure */
722 /* Interrupt setup */
723 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
724 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
725 link->irq.Handler = NULL;
727 link->conf.Attributes = 0;
728 link->conf.IntType = INT_MEMORY_AND_IO;
732 das16cs_pcmcia_config(link);
735 } /* das16cs_pcmcia_attach */
737 static void das16cs_pcmcia_detach(struct pcmcia_device *link)
739 DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link);
741 if (link->dev_node) {
742 ((struct local_info_t *) link->priv)->stop = 1;
743 das16cs_pcmcia_release(link);
745 /* This points to the parent struct local_info_t struct */
748 } /* das16cs_pcmcia_detach */
750 static void das16cs_pcmcia_config(struct pcmcia_device *link)
752 struct local_info_t *dev = link->priv;
755 int last_fn, last_ret;
757 cistpl_cftable_entry_t dflt = { 0 };
759 DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link);
762 This reads the card's CONFIG tuple to find its configuration
765 tuple.DesiredTuple = CISTPL_CONFIG;
766 tuple.Attributes = 0;
767 tuple.TupleData = buf;
768 tuple.TupleDataMax = sizeof(buf);
769 tuple.TupleOffset = 0;
771 last_fn = GetFirstTuple;
772 last_ret = pcmcia_get_first_tuple(link, &tuple);
776 last_fn = GetTupleData;
777 last_ret = pcmcia_get_tuple_data(link, &tuple);
781 last_fn = ParseTuple;
782 last_ret = pcmcia_parse_tuple(&tuple, &parse);
786 link->conf.ConfigBase = parse.config.base;
787 link->conf.Present = parse.config.rmask[0];
790 In this loop, we scan the CIS for configuration table entries,
791 each of which describes a valid card configuration, including
792 voltage, IO window, memory window, and interrupt settings.
794 We make no assumptions about the card to be configured: we use
795 just the information available in the CIS. In an ideal world,
796 this would work for any PCMCIA card, but it requires a complete
797 and accurate CIS. In practice, a driver usually "knows" most of
798 these things without consulting the CIS, and most client drivers
799 will only use the CIS to fill in implementation-defined details.
801 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
802 last_fn = GetFirstTuple;
804 last_ret = pcmcia_get_first_tuple(link, &tuple);
809 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
810 if (pcmcia_get_tuple_data(link, &tuple))
812 if (pcmcia_parse_tuple(&tuple, &parse))
815 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
819 link->conf.ConfigIndex = cfg->index;
821 /* Does this card need audio output? */
822 /* if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
823 link->conf.Attributes |= CONF_ENABLE_SPKR;
824 link->conf.Status = CCSR_AUDIO_ENA;
827 /* Do we need to allocate an interrupt? */
828 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
829 link->conf.Attributes |= CONF_ENABLE_IRQ;
831 /* IO window settings */
832 link->io.NumPorts1 = link->io.NumPorts2 = 0;
833 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
834 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
835 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
836 if (!(io->flags & CISTPL_IO_8BIT))
837 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
838 if (!(io->flags & CISTPL_IO_16BIT))
839 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
840 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
841 link->io.BasePort1 = io->win[0].base;
842 link->io.NumPorts1 = io->win[0].len;
844 link->io.Attributes2 = link->io.Attributes1;
845 link->io.BasePort2 = io->win[1].base;
846 link->io.NumPorts2 = io->win[1].len;
848 /* This reserves IO space but doesn't actually enable it */
849 if (pcmcia_request_io(link, &link->io))
853 /* If we got this far, we're cool! */
857 last_fn = GetNextTuple;
859 last_ret = pcmcia_get_next_tuple(link, &tuple);
865 Allocate an interrupt line. Note that this does not assign a
866 handler to the interrupt, unless the 'Handler' member of the
867 irq structure is initialized.
869 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
870 last_fn = RequestIRQ;
872 last_ret = pcmcia_request_irq(link, &link->irq);
877 This actually configures the PCMCIA socket -- setting up
878 the I/O windows and the interrupt mapping, and putting the
879 card and host interface into "Memory and IO" mode.
881 last_fn = RequestConfiguration;
882 last_ret = pcmcia_request_configuration(link, &link->conf);
887 At this point, the dev_node_t structure(s) need to be
888 initialized and arranged in a linked list at link->dev.
890 sprintf(dev->node.dev_name, "cb_das16_cs");
891 dev->node.major = dev->node.minor = 0;
892 link->dev_node = &dev->node;
894 /* Finally, report what we've done */
895 printk(KERN_INFO "%s: index 0x%02x",
896 dev->node.dev_name, link->conf.ConfigIndex);
897 if (link->conf.Attributes & CONF_ENABLE_IRQ)
898 printk(", irq %u", link->irq.AssignedIRQ);
899 if (link->io.NumPorts1)
900 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
901 link->io.BasePort1 + link->io.NumPorts1 - 1);
902 if (link->io.NumPorts2)
903 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
904 link->io.BasePort2 + link->io.NumPorts2 - 1);
910 cs_error(link, last_fn, last_ret);
911 das16cs_pcmcia_release(link);
912 } /* das16cs_pcmcia_config */
914 static void das16cs_pcmcia_release(struct pcmcia_device *link)
916 DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
917 pcmcia_disable_device(link);
918 } /* das16cs_pcmcia_release */
920 static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
922 struct local_info_t *local = link->priv;
924 /* Mark the device as stopped, to block IO until later */
928 } /* das16cs_pcmcia_suspend */
930 static int das16cs_pcmcia_resume(struct pcmcia_device *link)
932 struct local_info_t *local = link->priv;
936 } /* das16cs_pcmcia_resume */
938 /*====================================================================*/
940 static struct pcmcia_device_id das16cs_id_table[] = {
941 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
942 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
946 MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
948 struct pcmcia_driver das16cs_driver = {
949 .probe = das16cs_pcmcia_attach,
950 .remove = das16cs_pcmcia_detach,
951 .suspend = das16cs_pcmcia_suspend,
952 .resume = das16cs_pcmcia_resume,
953 .id_table = das16cs_id_table,
954 .owner = THIS_MODULE,
960 static int __init init_das16cs_pcmcia_cs(void)
962 DEBUG(0, "%s\n", version);
963 pcmcia_register_driver(&das16cs_driver);
967 static void __exit exit_das16cs_pcmcia_cs(void)
969 DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
970 pcmcia_unregister_driver(&das16cs_driver);
973 int __init init_module(void)
977 ret = init_das16cs_pcmcia_cs();
981 return comedi_driver_register(&driver_das16cs);
984 void __exit cleanup_module(void)
986 exit_das16cs_pcmcia_cs();
987 comedi_driver_unregister(&driver_das16cs);
991 COMEDI_INITCLEANUP(driver_das16cs);
992 #endif /* CONFIG_PCMCIA */