pcm3730.c revision b1e68ea5e1b0829037a1dc97e8a2ef4bb6e9c91d
1/*
2 * comedi/drivers/pcm3730.c
3 * Driver for PCM3730 and clones
4 * Blaine Lee
5 * from pcl725 by David S.
6 */
7/*
8Driver: pcm3730
9Description: PCM3730
10Author: Blaine Lee
11Devices: [Advantech] PCM-3730 (pcm3730)
12Status: unknown
13
14Configuration options:
15  [0] - I/O port base
16*/
17
18#include "../comedidev.h"
19
20#include <linux/ioport.h>
21
22#define PCM3730_SIZE 4		/*  consecutive io port addresses */
23
24#define PCM3730_DOA 0		/*  offsets for each port */
25#define PCM3730_DOB 2
26#define PCM3730_DOC 3
27#define PCM3730_DIA 0
28#define PCM3730_DIB 2
29#define PCM3730_DIC 3
30
31static int pcm3730_attach(struct comedi_device *dev,
32			  struct comedi_devconfig *it);
33static int pcm3730_detach(struct comedi_device *dev);
34static struct comedi_driver driver_pcm3730 = {
35	.driver_name = "pcm3730",
36	.module = THIS_MODULE,
37	.attach = pcm3730_attach,
38	.detach = pcm3730_detach,
39};
40
41COMEDI_INITCLEANUP(driver_pcm3730);
42
43static int pcm3730_do_insn_bits(struct comedi_device *dev,
44				struct comedi_subdevice *s,
45				struct comedi_insn *insn, unsigned int *data)
46{
47	if (insn->n != 2)
48		return -EINVAL;
49	if (data[0]) {
50		s->state &= ~data[0];
51		s->state |= (data[0] & data[1]);
52		outb(s->state, dev->iobase + (unsigned long)(s->private));
53	}
54	data[1] = s->state;
55
56	return 2;
57}
58
59static int pcm3730_di_insn_bits(struct comedi_device *dev,
60				struct comedi_subdevice *s,
61				struct comedi_insn *insn, unsigned int *data)
62{
63	if (insn->n != 2)
64		return -EINVAL;
65	data[1] = inb(dev->iobase + (unsigned long)(s->private));
66	return 2;
67}
68
69static int pcm3730_attach(struct comedi_device *dev,
70			  struct comedi_devconfig *it)
71{
72	struct comedi_subdevice *s;
73	unsigned long iobase;
74
75	iobase = it->options[0];
76	printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase);
77	if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) {
78		printk("I/O port conflict\n");
79		return -EIO;
80	}
81	dev->iobase = iobase;
82	dev->board_name = "pcm3730";
83	dev->iobase = dev->iobase;
84	dev->irq = 0;
85
86	if (alloc_subdevices(dev, 6) < 0)
87		return -ENOMEM;
88
89	s = dev->subdevices + 0;
90	s->type = COMEDI_SUBD_DO;
91	s->subdev_flags = SDF_WRITABLE;
92	s->maxdata = 1;
93	s->n_chan = 8;
94	s->insn_bits = pcm3730_do_insn_bits;
95	s->range_table = &range_digital;
96	s->private = (void *)PCM3730_DOA;
97
98	s = dev->subdevices + 1;
99	s->type = COMEDI_SUBD_DO;
100	s->subdev_flags = SDF_WRITABLE;
101	s->maxdata = 1;
102	s->n_chan = 8;
103	s->insn_bits = pcm3730_do_insn_bits;
104	s->range_table = &range_digital;
105	s->private = (void *)PCM3730_DOB;
106
107	s = dev->subdevices + 2;
108	s->type = COMEDI_SUBD_DO;
109	s->subdev_flags = SDF_WRITABLE;
110	s->maxdata = 1;
111	s->n_chan = 8;
112	s->insn_bits = pcm3730_do_insn_bits;
113	s->range_table = &range_digital;
114	s->private = (void *)PCM3730_DOC;
115
116	s = dev->subdevices + 3;
117	s->type = COMEDI_SUBD_DI;
118	s->subdev_flags = SDF_READABLE;
119	s->maxdata = 1;
120	s->n_chan = 8;
121	s->insn_bits = pcm3730_di_insn_bits;
122	s->range_table = &range_digital;
123	s->private = (void *)PCM3730_DIA;
124
125	s = dev->subdevices + 4;
126	s->type = COMEDI_SUBD_DI;
127	s->subdev_flags = SDF_READABLE;
128	s->maxdata = 1;
129	s->n_chan = 8;
130	s->insn_bits = pcm3730_di_insn_bits;
131	s->range_table = &range_digital;
132	s->private = (void *)PCM3730_DIB;
133
134	s = dev->subdevices + 5;
135	s->type = COMEDI_SUBD_DI;
136	s->subdev_flags = SDF_READABLE;
137	s->maxdata = 1;
138	s->n_chan = 8;
139	s->insn_bits = pcm3730_di_insn_bits;
140	s->range_table = &range_digital;
141	s->private = (void *)PCM3730_DIC;
142
143	printk(KERN_INFO "\n");
144
145	return 0;
146}
147
148static int pcm3730_detach(struct comedi_device *dev)
149{
150	printk(KERN_INFO "comedi%d: pcm3730: remove\n", dev->minor);
151
152	if (dev->iobase)
153		release_region(dev->iobase, PCM3730_SIZE);
154
155	return 0;
156}
157