pcl725.c revision 0a85b6f0ab0d2edb0d41b32697111ce0e4f43496
1/*
2 * comedi/drivers/pcl725.c
3 * Driver for PCL725 and clones
4 * David A. Schleef
5 */
6/*
7Driver: pcl725
8Description: Advantech PCL-725 (& compatibles)
9Author: ds
10Status: unknown
11Devices: [Advantech] PCL-725 (pcl725)
12*/
13
14#include "../comedidev.h"
15
16#include <linux/ioport.h>
17
18#define PCL725_SIZE 2
19
20#define PCL725_DO 0
21#define PCL725_DI 1
22
23static int pcl725_attach(struct comedi_device *dev,
24			 struct comedi_devconfig *it);
25static int pcl725_detach(struct comedi_device *dev);
26static struct comedi_driver driver_pcl725 = {
27	.driver_name = "pcl725",
28	.module = THIS_MODULE,
29	.attach = pcl725_attach,
30	.detach = pcl725_detach,
31};
32
33COMEDI_INITCLEANUP(driver_pcl725);
34
35static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
36			  struct comedi_insn *insn, unsigned int *data)
37{
38	if (insn->n != 2)
39		return -EINVAL;
40
41	if (data[0]) {
42		s->state &= ~data[0];
43		s->state |= (data[0] & data[1]);
44		outb(s->state, dev->iobase + PCL725_DO);
45	}
46
47	data[1] = s->state;
48
49	return 2;
50}
51
52static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
53			  struct comedi_insn *insn, unsigned int *data)
54{
55	if (insn->n != 2)
56		return -EINVAL;
57
58	data[1] = inb(dev->iobase + PCL725_DI);
59
60	return 2;
61}
62
63static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
64{
65	struct comedi_subdevice *s;
66	unsigned long iobase;
67
68	iobase = it->options[0];
69	printk("comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
70	if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
71		printk("I/O port conflict\n");
72		return -EIO;
73	}
74	dev->board_name = "pcl725";
75	dev->iobase = iobase;
76	dev->irq = 0;
77
78	if (alloc_subdevices(dev, 2) < 0)
79		return -ENOMEM;
80
81	s = dev->subdevices + 0;
82	/* do */
83	s->type = COMEDI_SUBD_DO;
84	s->subdev_flags = SDF_WRITABLE;
85	s->maxdata = 1;
86	s->n_chan = 8;
87	s->insn_bits = pcl725_do_insn;
88	s->range_table = &range_digital;
89
90	s = dev->subdevices + 1;
91	/* di */
92	s->type = COMEDI_SUBD_DI;
93	s->subdev_flags = SDF_READABLE;
94	s->maxdata = 1;
95	s->n_chan = 8;
96	s->insn_bits = pcl725_di_insn;
97	s->range_table = &range_digital;
98
99	printk("\n");
100
101	return 0;
102}
103
104static int pcl725_detach(struct comedi_device *dev)
105{
106	printk("comedi%d: pcl725: remove\n", dev->minor);
107
108	if (dev->iobase)
109		release_region(dev->iobase, PCL725_SIZE);
110
111	return 0;
112}
113