aio_iiro_16.c revision e20ad20d849eb902628553be1fd2dc9ccc40a4bd
1/*
2
3    comedi/drivers/aio_iiro_16.c
4
5    Driver for Acces I/O Products PC-104 AIO-IIRO-16 Digital I/O board
6    Copyright (C) 2006 C&C Technologies, Inc.
7
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.
12
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.
17
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.
21*/
22
23/*
24
25Driver: aio_iiro_16
26Description: Acces I/O Products PC-104 IIRO16 Relay And Isolated Input Board
27Author: Zachary Ware <zach.ware@cctechnol.com>
28Devices:
29 [Acces I/O] PC-104 AIO12-8
30Status: experimental
31
32Configuration Options:
33  [0] - I/O port base address
34
35*/
36
37#include "../comedidev.h"
38#include <linux/ioport.h>
39
40#define AIO_IIRO_16_SIZE	0x08
41#define AIO_IIRO_16_RELAY_0_7	0x00
42#define AIO_IIRO_16_INPUT_0_7	0x01
43#define AIO_IIRO_16_IRQ		0x02
44#define AIO_IIRO_16_RELAY_8_15	0x04
45#define AIO_IIRO_16_INPUT_8_15	0x05
46
47struct aio_iiro_16_board {
48	const char *name;
49	int do_;
50	int di;
51};
52
53static const struct aio_iiro_16_board aio_iiro_16_boards[] = {
54	{
55	 .name = "aio_iiro_16",
56	 .di = 16,
57	 .do_ = 16},
58};
59
60#define	thisboard	((const struct aio_iiro_16_board *) dev->board_ptr)
61
62struct aio_iiro_16_private {
63	int data;
64	struct pci_dev *pci_dev;
65	unsigned int ao_readback[2];
66};
67
68#define	devpriv	((struct aio_iiro_16_private *) dev->private)
69
70static int aio_iiro_16_attach(struct comedi_device *dev,
71			      struct comedi_devconfig *it);
72
73static int aio_iiro_16_detach(struct comedi_device *dev);
74
75static struct comedi_driver driver_aio_iiro_16 = {
76	.driver_name = "aio_iiro_16",
77	.module = THIS_MODULE,
78	.attach = aio_iiro_16_attach,
79	.detach = aio_iiro_16_detach,
80	.board_name = &aio_iiro_16_boards[0].name,
81	.offset = sizeof(struct aio_iiro_16_board),
82	.num_names = ARRAY_SIZE(aio_iiro_16_boards),
83};
84
85static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
86					  struct comedi_subdevice *s,
87					  struct comedi_insn *insn,
88					  unsigned int *data);
89
90static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
91					   struct comedi_subdevice *s,
92					   struct comedi_insn *insn,
93					   unsigned int *data);
94
95static int aio_iiro_16_attach(struct comedi_device *dev,
96			      struct comedi_devconfig *it)
97{
98	int iobase;
99	struct comedi_subdevice *s;
100
101	printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor);
102
103	dev->board_name = thisboard->name;
104
105	iobase = it->options[0];
106
107	if (!request_region(iobase, AIO_IIRO_16_SIZE, dev->board_name)) {
108		printk("I/O port conflict");
109		return -EIO;
110	}
111
112	dev->iobase = iobase;
113
114	if (alloc_private(dev, sizeof(struct aio_iiro_16_private)) < 0)
115		return -ENOMEM;
116
117	if (alloc_subdevices(dev, 2) < 0)
118		return -ENOMEM;
119
120	s = dev->subdevices + 0;
121	s->type = COMEDI_SUBD_DIO;
122	s->subdev_flags = SDF_WRITABLE;
123	s->n_chan = 16;
124	s->maxdata = 1;
125	s->range_table = &range_digital;
126	s->insn_bits = aio_iiro_16_dio_insn_bits_write;
127
128	s = dev->subdevices + 1;
129	s->type = COMEDI_SUBD_DIO;
130	s->subdev_flags = SDF_READABLE;
131	s->n_chan = 16;
132	s->maxdata = 1;
133	s->range_table = &range_digital;
134	s->insn_bits = aio_iiro_16_dio_insn_bits_read;
135
136	printk("attached\n");
137
138	return 1;
139}
140
141static int aio_iiro_16_detach(struct comedi_device *dev)
142{
143	printk(KERN_INFO "comedi%d: aio_iiro_16: remove\n", dev->minor);
144
145	if (dev->iobase)
146		release_region(dev->iobase, AIO_IIRO_16_SIZE);
147
148	return 0;
149}
150
151static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
152					   struct comedi_subdevice *s,
153					   struct comedi_insn *insn,
154					   unsigned int *data)
155{
156	if (insn->n != 2)
157		return -EINVAL;
158
159	if (data[0]) {
160		s->state &= ~data[0];
161		s->state |= data[0] & data[1];
162		outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
163		outb((s->state >> 8) & 0xff,
164		     dev->iobase + AIO_IIRO_16_RELAY_8_15);
165	}
166
167	data[1] = s->state;
168
169	return 2;
170}
171
172static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
173					  struct comedi_subdevice *s,
174					  struct comedi_insn *insn,
175					  unsigned int *data)
176{
177	if (insn->n != 2)
178		return -EINVAL;
179
180	data[1] = 0;
181	data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7);
182	data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8;
183
184	return 2;
185}
186
187COMEDI_INITCLEANUP(driver_aio_iiro_16);
188