2 * comedi/drivers/ni_daq_700.c
3 * Driver for DAQCard-700 DIO only
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 Description: National Instruments PCMCIA DAQCard-700 DIO only
28 Author: Fred Brooks <nsaspook@nsaspook.com>,
29 based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
30 Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
32 Updated: Thu, 21 Feb 2008 12:07:20 +0000
34 The daqcard-700 appears in Comedi as a single digital I/O subdevice with
35 16 channels. The channel 0 corresponds to the daqcard-700's output
36 port, bit 0; channel 8 corresponds to the input port, bit 0.
38 Direction configuration: channels 0-7 output, 8-15 input (8225 device
39 emu as port A output, port B input, port C N/A).
41 IRQ is assigned but not used.
44 #include <linux/interrupt.h>
45 #include <linux/slab.h>
46 #include "../comedidev.h"
48 #include <linux/ioport.h>
50 #include <pcmcia/cistpl.h>
51 #include <pcmcia/cisreg.h>
52 #include <pcmcia/ds.h>
54 static struct pcmcia_device *pcmcia_cur_dev = NULL;
56 #define DIO700_SIZE 8 /* size of io region used by board */
58 static int dio700_attach(struct comedi_device *dev,
59 struct comedi_devconfig *it);
60 static int dio700_detach(struct comedi_device *dev);
62 enum dio700_bustype { pcmcia_bustype };
66 int device_id; /* device id for pcmcia board */
67 enum dio700_bustype bustype; /* PCMCIA */
68 int have_dio; /* have daqcard-700 dio */
69 /* function pointers so we can use inb/outb or readb/writeb */
71 unsigned int (*read_byte) (unsigned int address);
72 void (*write_byte) (unsigned int byte, unsigned int address);
75 static const struct dio700_board dio700_boards[] = {
77 .name = "daqcard-700",
78 /* 0x10b is manufacturer id, 0x4743 is device id */
80 .bustype = pcmcia_bustype,
85 /* 0x10b is manufacturer id, 0x4743 is device id */
87 .bustype = pcmcia_bustype,
93 * Useful for shorthand access to the particular board structure
95 #define thisboard ((const struct dio700_board *)dev->board_ptr)
97 struct dio700_private {
99 int data; /* number of data points left to be taken */
102 #define devpriv ((struct dio700_private *)dev->private)
104 static struct comedi_driver driver_dio700 = {
105 .driver_name = "ni_daq_700",
106 .module = THIS_MODULE,
107 .attach = dio700_attach,
108 .detach = dio700_detach,
109 .num_names = ARRAY_SIZE(dio700_boards),
110 .board_name = &dio700_boards[0].name,
111 .offset = sizeof(struct dio700_board),
114 /* the real driver routines */
123 struct subdev_700_struct {
124 unsigned long cb_arg;
125 int (*cb_func) (int, int, int, unsigned long);
129 #define CALLBACK_ARG (((struct subdev_700_struct *)s->private)->cb_arg)
130 #define CALLBACK_FUNC (((struct subdev_700_struct *)s->private)->cb_func)
131 #define subdevpriv ((struct subdev_700_struct *)s->private)
133 static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
135 void subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
139 d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
141 comedi_buf_put(s->async, d);
142 s->async->events |= COMEDI_CB_EOS;
144 comedi_event(dev, s);
146 EXPORT_SYMBOL(subdev_700_interrupt);
148 static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
150 /* port is always A for output and B for input (8255 emu) */
151 unsigned long iobase = arg;
154 outb(data, iobase + DIO_W);
157 return inb(iobase + DIO_R);
161 static int subdev_700_insn(struct comedi_device *dev,
162 struct comedi_subdevice *s, struct comedi_insn *insn,
166 s->state &= ~data[0];
167 s->state |= (data[0] & data[1]);
170 CALLBACK_FUNC(1, _700_DATA, s->state & 0xff,
174 data[1] = s->state & 0xff;
175 data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8;
180 static int subdev_700_insn_config(struct comedi_device *dev,
181 struct comedi_subdevice *s,
182 struct comedi_insn *insn, unsigned int *data)
186 case INSN_CONFIG_DIO_INPUT:
188 case INSN_CONFIG_DIO_OUTPUT:
190 case INSN_CONFIG_DIO_QUERY:
193 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
204 static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
205 { /* use powerup defaults */
209 static int subdev_700_cmdtest(struct comedi_device *dev,
210 struct comedi_subdevice *s,
211 struct comedi_cmd *cmd)
218 tmp = cmd->start_src;
219 cmd->start_src &= TRIG_NOW;
220 if (!cmd->start_src || tmp != cmd->start_src)
223 tmp = cmd->scan_begin_src;
224 cmd->scan_begin_src &= TRIG_EXT;
225 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
228 tmp = cmd->convert_src;
229 cmd->convert_src &= TRIG_FOLLOW;
230 if (!cmd->convert_src || tmp != cmd->convert_src)
233 tmp = cmd->scan_end_src;
234 cmd->scan_end_src &= TRIG_COUNT;
235 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
239 cmd->stop_src &= TRIG_NONE;
240 if (!cmd->stop_src || tmp != cmd->stop_src)
253 if (cmd->start_arg != 0) {
257 if (cmd->scan_begin_arg != 0) {
258 cmd->scan_begin_arg = 0;
261 if (cmd->convert_arg != 0) {
262 cmd->convert_arg = 0;
265 if (cmd->scan_end_arg != 1) {
266 cmd->scan_end_arg = 1;
269 if (cmd->stop_arg != 0) {
285 static int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
292 static int subdev_700_cancel(struct comedi_device *dev,
293 struct comedi_subdevice *s)
300 int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
301 int (*cb) (int, int, int, unsigned long), unsigned long arg)
303 s->type = COMEDI_SUBD_DIO;
304 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
306 s->range_table = &range_digital;
309 s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL);
315 CALLBACK_FUNC = subdev_700_cb;
319 s->insn_bits = subdev_700_insn;
320 s->insn_config = subdev_700_insn_config;
328 EXPORT_SYMBOL(subdev_700_init);
330 int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
331 int (*cb) (int, int, int, unsigned long),
336 ret = subdev_700_init(dev, s, cb, arg);
340 s->do_cmdtest = subdev_700_cmdtest;
341 s->do_cmd = subdev_700_cmd;
342 s->cancel = subdev_700_cancel;
344 subdevpriv->have_irq = 1;
348 EXPORT_SYMBOL(subdev_700_init_irq);
350 void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
353 if (subdevpriv->have_irq)
357 EXPORT_SYMBOL(subdev_700_cleanup);
359 static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
361 struct comedi_subdevice *s;
362 unsigned long iobase = 0;
364 unsigned int irq = 0;
366 struct pcmcia_device *link;
368 /* allocate and initialize dev->private */
369 if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
372 /* get base address, irq etc. based on bustype */
373 switch (thisboard->bustype) {
375 link = pcmcia_cur_dev; /* XXX hack */
378 iobase = link->resource[0]->start;
384 printk("bug! couldn't determine board type\n");
388 printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
389 thisboard->name, iobase);
392 printk(", irq %u", irq);
399 printk("io base address is zero!\n");
403 dev->iobase = iobase;
410 dev->board_name = thisboard->name;
412 if (alloc_subdevices(dev, 1) < 0)
415 /* DAQCard-700 dio */
416 s = dev->subdevices + 0;
417 subdev_700_init(dev, s, NULL, dev->iobase);
422 static int dio700_detach(struct comedi_device *dev)
424 printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
427 subdev_700_cleanup(dev, dev->subdevices + 0);
429 if (thisboard->bustype != pcmcia_bustype && dev->iobase)
430 release_region(dev->iobase, DIO700_SIZE);
432 free_irq(dev->irq, dev);
437 static void dio700_config(struct pcmcia_device *link);
438 static void dio700_release(struct pcmcia_device *link);
439 static int dio700_cs_suspend(struct pcmcia_device *p_dev);
440 static int dio700_cs_resume(struct pcmcia_device *p_dev);
442 static int dio700_cs_attach(struct pcmcia_device *);
443 static void dio700_cs_detach(struct pcmcia_device *);
445 struct local_info_t {
446 struct pcmcia_device *link;
448 struct bus_operations *bus;
451 static int dio700_cs_attach(struct pcmcia_device *link)
453 struct local_info_t *local;
455 printk(KERN_INFO "ni_daq_700: cs-attach\n");
457 dev_dbg(&link->dev, "dio700_cs_attach()\n");
459 /* Allocate space for private device-specific data */
460 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
466 pcmcia_cur_dev = link;
471 } /* dio700_cs_attach */
473 static void dio700_cs_detach(struct pcmcia_device *link)
476 printk(KERN_INFO "ni_daq_700: cs-detach!\n");
478 dev_dbg(&link->dev, "dio700_cs_detach\n");
480 ((struct local_info_t *)link->priv)->stop = 1;
481 dio700_release(link);
483 /* This points to the parent struct local_info_t struct */
486 } /* dio700_cs_detach */
488 static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
491 if (p_dev->config_index == 0)
494 return pcmcia_request_io(p_dev);
497 static void dio700_config(struct pcmcia_device *link)
502 printk(KERN_INFO "ni_daq_700: cs-config\n");
504 dev_dbg(&link->dev, "dio700_config\n");
506 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
509 ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
511 dev_warn(&link->dev, "no configuration found\n");
518 ret = pcmcia_enable_device(link);
525 printk(KERN_INFO "ni_daq_700 cs failed");
526 dio700_release(link);
528 } /* dio700_config */
530 static void dio700_release(struct pcmcia_device *link)
532 dev_dbg(&link->dev, "dio700_release\n");
534 pcmcia_disable_device(link);
535 } /* dio700_release */
537 static int dio700_cs_suspend(struct pcmcia_device *link)
539 struct local_info_t *local = link->priv;
541 /* Mark the device as stopped, to block IO until later */
544 } /* dio700_cs_suspend */
546 static int dio700_cs_resume(struct pcmcia_device *link)
548 struct local_info_t *local = link->priv;
552 } /* dio700_cs_resume */
554 /*====================================================================*/
556 static struct pcmcia_device_id dio700_cs_ids[] = {
557 /* N.B. These IDs should match those in dio700_boards */
558 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743), /* daqcard-700 */
563 MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
564 MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
565 MODULE_DESCRIPTION("Comedi driver for National Instruments "
566 "PCMCIA DAQCard-700 DIO");
567 MODULE_LICENSE("GPL");
569 struct pcmcia_driver dio700_cs_driver = {
570 .probe = dio700_cs_attach,
571 .remove = dio700_cs_detach,
572 .suspend = dio700_cs_suspend,
573 .resume = dio700_cs_resume,
574 .id_table = dio700_cs_ids,
575 .owner = THIS_MODULE,
576 .name = "ni_daq_700",
579 static int __init init_dio700_cs(void)
581 pcmcia_register_driver(&dio700_cs_driver);
585 static void __exit exit_dio700_cs(void)
587 pr_debug("ni_daq_700: unloading\n");
588 pcmcia_unregister_driver(&dio700_cs_driver);
591 int __init init_module(void)
595 ret = init_dio700_cs();
599 return comedi_driver_register(&driver_dio700);
602 void __exit cleanup_module(void)
605 comedi_driver_unregister(&driver_dio700);