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 "../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>
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 typedef struct das16cs_board_struct {
62 static const das16cs_board das16cs_boards[] = {
64 device_id:0x0000,/* unknown */
65 name: "PC-CARD DAS16/16",
70 name: "PC-CARD DAS16/16-AO",
75 name: "PCM-DAS16s/16",
80 #define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
81 #define thisboard ((const das16cs_board *)dev->board_ptr)
84 struct pcmcia_device *link;
86 unsigned int ao_readback[2];
87 unsigned short status1;
88 unsigned short status2;
90 #define devpriv ((das16cs_private *)dev->private)
92 static int das16cs_attach(struct comedi_device * dev, 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",
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, {
111 static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
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)
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]);
149 static const das16cs_board *das16cs_probe(struct comedi_device * dev,
150 struct pcmcia_device *link)
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");
168 static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it)
170 struct pcmcia_device *link;
171 struct comedi_subdevice *s;
175 printk("comedi%d: cb_das16_cs: ", dev->minor);
177 link = cur_dev; /* XXX hack */
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));
190 ret = comedi_request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
191 IRQF_SHARED, "cb_das16_cs", dev);
195 dev->irq = link->irq.AssignedIRQ;
196 printk("irq=%u ", dev->irq);
198 dev->board_ptr = das16cs_probe(dev, link);
202 dev->board_name = thisboard->name;
204 if (alloc_private(dev, sizeof(das16cs_private)) < 0)
207 if (alloc_subdevices(dev, 4) < 0)
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;
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;
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 */
238 s->type = COMEDI_SUBD_DIO;
239 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
242 s->range_table = &range_digital;
243 s->insn_bits = das16cs_dio_insn_bits;
244 s->insn_config = das16cs_dio_insn_config;
246 s->type = COMEDI_SUBD_UNUSED;
249 s = dev->subdevices + 3;
250 /* timer subdevice */
252 s->type = COMEDI_SUBD_TIMER;
253 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
256 s->range_table = &range_unknown;
257 s->insn_read = das16cs_timer_insn_read;
258 s->insn_config = das16cs_timer_insn_config;
260 s->type = COMEDI_SUBD_UNUSED;
263 printk("attached\n");
268 static int das16cs_detach(struct comedi_device * dev)
270 printk("comedi%d: das16cs: remove\n", dev->minor);
273 comedi_free_irq(dev->irq, dev);
279 static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
281 //struct comedi_device *dev = d;
286 * "instructions" read/write data in "one-shot" or "software-triggered"
289 static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
290 struct comedi_insn * insn, unsigned int * data)
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);
317 for (to = 0; to < TIMEOUT; to++) {
318 if (inw(dev->iobase + 4) & 0x0080)
322 printk("cb_das16_cs: ai timeout\n");
325 data[i] = (unsigned short)inw(dev->iobase + 0);
331 static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
336 static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
337 struct comedi_cmd * cmd)
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)
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)
361 tmp = cmd->convert_src;
362 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
363 if (!cmd->convert_src || tmp != cmd->convert_src)
366 tmp = cmd->scan_end_src;
367 cmd->scan_end_src &= TRIG_COUNT;
368 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
372 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
373 if (!cmd->stop_src || tmp != cmd->stop_src)
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)
385 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
387 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
393 /* step 3: make sure arguments are trivially compatible */
395 if (cmd->start_arg != 0) {
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;
407 if (cmd->scan_begin_arg > MIN_SPEED) {
408 cmd->scan_begin_arg = MIN_SPEED;
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;
420 if (cmd->convert_src == TRIG_TIMER) {
421 if (cmd->convert_arg < MAX_SPEED) {
422 cmd->convert_arg = MAX_SPEED;
425 if (cmd->convert_arg > MIN_SPEED) {
426 cmd->convert_arg = MIN_SPEED;
430 /* external trigger */
432 if (cmd->convert_arg > 9) {
433 cmd->convert_arg = 9;
438 if (cmd->scan_end_arg != cmd->chanlist_len) {
439 cmd->scan_end_arg = cmd->chanlist_len;
442 if (cmd->stop_src == TRIG_COUNT) {
443 if (cmd->stop_arg > 0x00ffffff) {
444 cmd->stop_arg = 0x00ffffff;
449 if (cmd->stop_arg != 0) {
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)
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)
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;
492 static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
493 struct comedi_insn * insn, unsigned int * data)
496 int chan = CR_CHAN(insn->chanspec);
497 unsigned short status1;
501 for (i = 0; i < insn->n; i++) {
502 devpriv->ao_readback[chan] = data[i];
505 outw(devpriv->status1, dev->iobase + 4);
508 status1 = devpriv->status1 & ~0xf;
514 /* printk("0x%04x\n",status1);*/
515 outw(status1, dev->iobase + 4);
518 for (bit = 15; bit >= 0; bit--) {
519 int b = (d >> bit) & 0x1;
521 /* printk("0x%04x\n",status1 | b | 0x0000);*/
522 outw(status1 | b | 0x0000, dev->iobase + 4);
524 /* printk("0x%04x\n",status1 | b | 0x0004);*/
525 outw(status1 | b | 0x0004, dev->iobase + 4);
528 /* make high both DAC0CS and DAC1CS to load
529 new data and update analog output*/
530 outw(status1 | 0x9, dev->iobase + 4);
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)
542 int chan = CR_CHAN(insn->chanspec);
544 for (i = 0; i < insn->n; i++)
545 data[i] = devpriv->ao_readback[chan];
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)
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);
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);
587 case INSN_CONFIG_DIO_OUTPUT:
590 case INSN_CONFIG_DIO_INPUT:
593 case INSN_CONFIG_DIO_QUERY:
596 io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
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);
613 static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
614 struct comedi_insn * insn, unsigned int * data)
619 static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
620 struct comedi_insn * insn, unsigned int * data)
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)
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)";
654 #define DEBUG(n, args...)
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
686 static dev_info_t dev_info = "cb_das16_cs";
688 typedef struct local_info_t {
689 struct pcmcia_device *link;
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
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)
711 DEBUG(0, "das16cs_pcmcia_attach()\n");
713 /* Allocate space for private device-specific data */
714 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
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;
731 das16cs_pcmcia_config(link);
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 ((local_info_t *) link->priv)->stop = 1;
742 das16cs_pcmcia_release(link);
744 /* This points to the parent local_info_t struct */
747 } /* das16cs_pcmcia_detach */
749 static void das16cs_pcmcia_config(struct pcmcia_device *link)
751 local_info_t *dev = link->priv;
754 int last_fn, last_ret;
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
764 tuple.DesiredTuple = CISTPL_CONFIG;
765 tuple.Attributes = 0;
766 tuple.TupleData = buf;
767 tuple.TupleDataMax = sizeof(buf);
768 tuple.TupleOffset = 0;
769 last_fn = GetFirstTuple;
770 if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
772 last_fn = GetTupleData;
773 if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0)
775 last_fn = ParseTuple;
776 if ((last_ret = pcmcia_parse_tuple(link, &tuple, &parse)) != 0)
778 link->conf.ConfigBase = parse.config.base;
779 link->conf.Present = parse.config.rmask[0];
782 In this loop, we scan the CIS for configuration table entries,
783 each of which describes a valid card configuration, including
784 voltage, IO window, memory window, and interrupt settings.
786 We make no assumptions about the card to be configured: we use
787 just the information available in the CIS. In an ideal world,
788 this would work for any PCMCIA card, but it requires a complete
789 and accurate CIS. In practice, a driver usually "knows" most of
790 these things without consulting the CIS, and most client drivers
791 will only use the CIS to fill in implementation-defined details.
793 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
794 last_fn = GetFirstTuple;
795 if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
798 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
799 if (pcmcia_get_tuple_data(link, &tuple))
801 if (pcmcia_parse_tuple(link, &tuple, &parse))
804 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
808 link->conf.ConfigIndex = cfg->index;
810 /* Does this card need audio output? */
811 /* if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
812 link->conf.Attributes |= CONF_ENABLE_SPKR;
813 link->conf.Status = CCSR_AUDIO_ENA;
816 /* Do we need to allocate an interrupt? */
817 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
818 link->conf.Attributes |= CONF_ENABLE_IRQ;
820 /* IO window settings */
821 link->io.NumPorts1 = link->io.NumPorts2 = 0;
822 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
823 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
824 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
825 if (!(io->flags & CISTPL_IO_8BIT))
826 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
827 if (!(io->flags & CISTPL_IO_16BIT))
828 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
829 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
830 link->io.BasePort1 = io->win[0].base;
831 link->io.NumPorts1 = io->win[0].len;
833 link->io.Attributes2 = link->io.Attributes1;
834 link->io.BasePort2 = io->win[1].base;
835 link->io.NumPorts2 = io->win[1].len;
837 /* This reserves IO space but doesn't actually enable it */
838 if (pcmcia_request_io(link, &link->io))
842 /* If we got this far, we're cool! */
846 last_fn = GetNextTuple;
847 if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0)
852 Allocate an interrupt line. Note that this does not assign a
853 handler to the interrupt, unless the 'Handler' member of the
854 irq structure is initialized.
856 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
857 last_fn = RequestIRQ;
858 if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0)
862 This actually configures the PCMCIA socket -- setting up
863 the I/O windows and the interrupt mapping, and putting the
864 card and host interface into "Memory and IO" mode.
866 last_fn = RequestConfiguration;
867 if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0)
871 At this point, the dev_node_t structure(s) need to be
872 initialized and arranged in a linked list at link->dev.
874 sprintf(dev->node.dev_name, "cb_das16_cs");
875 dev->node.major = dev->node.minor = 0;
876 link->dev_node = &dev->node;
878 /* Finally, report what we've done */
879 printk(KERN_INFO "%s: index 0x%02x",
880 dev->node.dev_name, link->conf.ConfigIndex);
881 if (link->conf.Attributes & CONF_ENABLE_IRQ)
882 printk(", irq %u", link->irq.AssignedIRQ);
883 if (link->io.NumPorts1)
884 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
885 link->io.BasePort1 + link->io.NumPorts1 - 1);
886 if (link->io.NumPorts2)
887 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
888 link->io.BasePort2 + link->io.NumPorts2 - 1);
894 cs_error(link, last_fn, last_ret);
895 das16cs_pcmcia_release(link);
896 } /* das16cs_pcmcia_config */
898 static void das16cs_pcmcia_release(struct pcmcia_device *link)
900 DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
901 pcmcia_disable_device(link);
902 } /* das16cs_pcmcia_release */
904 static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
906 local_info_t *local = link->priv;
908 /* Mark the device as stopped, to block IO until later */
912 } /* das16cs_pcmcia_suspend */
914 static int das16cs_pcmcia_resume(struct pcmcia_device *link)
916 local_info_t *local = link->priv;
920 } /* das16cs_pcmcia_resume */
922 /*====================================================================*/
924 static struct pcmcia_device_id das16cs_id_table[] = {
925 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
926 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
930 MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
932 struct pcmcia_driver das16cs_driver = {
933 .probe = das16cs_pcmcia_attach,
934 .remove = das16cs_pcmcia_detach,
935 .suspend = das16cs_pcmcia_suspend,
936 .resume = das16cs_pcmcia_resume,
937 .id_table = das16cs_id_table,
938 .owner = THIS_MODULE,
944 static int __init init_das16cs_pcmcia_cs(void)
946 DEBUG(0, "%s\n", version);
947 pcmcia_register_driver(&das16cs_driver);
951 static void __exit exit_das16cs_pcmcia_cs(void)
953 DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
954 pcmcia_unregister_driver(&das16cs_driver);
957 int __init init_module(void)
961 ret = init_das16cs_pcmcia_cs();
965 return comedi_driver_register(&driver_das16cs);
968 void __exit cleanup_module(void)
970 exit_das16cs_pcmcia_cs();
971 comedi_driver_unregister(&driver_das16cs);
975 COMEDI_INITCLEANUP(driver_das16cs);
976 #endif //CONFIG_PCMCIA