Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
staging
comedi
drivers
aio_aio12_8.c
Go to the documentation of this file.
1
/*
2
3
comedi/drivers/aio_aio12_8.c
4
5
Driver for Access I/O Products PC-104 AIO12-8 Analog 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
25
Driver: aio_aio12_8
26
Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board
27
Author: Pablo Mejia <
[email protected]
>
28
Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8)
29
[Access I/O] PC-104 AI12-8 (aio_ai12_8)
30
[Access I/O] PC-104 AO12-8 (aio_ao12_8)
31
Status: experimental
32
33
Configuration Options:
34
[0] - I/O port base address
35
36
Notes:
37
38
Only synchronous operations are supported.
39
40
*/
41
42
#include "../comedidev.h"
43
#include <
linux/ioport.h
>
44
#include "
8255.h
"
45
46
/*
47
* Register map
48
*/
49
#define AIO12_8_STATUS_REG 0x00
50
#define AIO12_8_STATUS_ADC_EOC (1 << 7)
51
#define AIO12_8_STATUS_PORT_C_COS (1 << 6)
52
#define AIO12_8_STATUS_IRQ_ENA (1 << 2)
53
#define AIO12_8_INTERRUPT_REG 0x01
54
#define AIO12_8_INTERRUPT_ADC (1 << 7)
55
#define AIO12_8_INTERRUPT_COS (1 << 6)
56
#define AIO12_8_INTERRUPT_COUNTER1 (1 << 5)
57
#define AIO12_8_INTERRUPT_PORT_C3 (1 << 4)
58
#define AIO12_8_INTERRUPT_PORT_C0 (1 << 3)
59
#define AIO12_8_INTERRUPT_ENA (1 << 2)
60
#define AIO12_8_ADC_REG 0x02
61
#define AIO12_8_ADC_MODE_NORMAL (0 << 6)
62
#define AIO12_8_ADC_MODE_INT_CLK (1 << 6)
63
#define AIO12_8_ADC_MODE_STANDBY (2 << 6)
64
#define AIO12_8_ADC_MODE_POWERDOWN (3 << 6)
65
#define AIO12_8_ADC_ACQ_3USEC (0 << 5)
66
#define AIO12_8_ADC_ACQ_PROGRAM (1 << 5)
67
#define AIO12_8_ADC_RANGE(x) ((x) << 3)
68
#define AIO12_8_ADC_CHAN(x) ((x) << 0)
69
#define AIO12_8_DAC_REG(x) (0x04 + (x) * 2)
70
#define AIO12_8_8254_BASE_REG 0x0c
71
#define AIO12_8_8255_BASE_REG 0x10
72
#define AIO12_8_DIO_CONTROL_REG 0x14
73
#define AIO12_8_DIO_CONTROL_TST (1 << 0)
74
#define AIO12_8_ADC_TRIGGER_REG 0x15
75
#define AIO12_8_ADC_TRIGGER_RANGE(x) ((x) << 3)
76
#define AIO12_8_ADC_TRIGGER_CHAN(x) ((x) << 0)
77
#define AIO12_8_TRIGGER_REG 0x16
78
#define AIO12_8_TRIGGER_ADTRIG (1 << 1)
79
#define AIO12_8_TRIGGER_DACTRIG (1 << 0)
80
#define AIO12_8_COS_REG 0x17
81
#define AIO12_8_DAC_ENABLE_REG 0x18
82
#define AIO12_8_DAC_ENABLE_REF_ENA (1 << 0)
83
84
struct
aio12_8_boardtype
{
85
const
char
*
name
;
86
int
ai_nchan
;
87
int
ao_nchan
;
88
};
89
90
static
const
struct
aio12_8_boardtype
board_types[] = {
91
{
92
.name =
"aio_aio12_8"
,
93
.ai_nchan = 8,
94
.ao_nchan = 4,
95
}, {
96
.name =
"aio_ai12_8"
,
97
.ai_nchan = 8,
98
}, {
99
.name =
"aio_ao12_8"
,
100
.ao_nchan = 4,
101
},
102
};
103
104
struct
aio12_8_private
{
105
unsigned
int
ao_readback
[4];
106
};
107
108
static
int
aio_aio12_8_ai_read(
struct
comedi_device
*
dev
,
109
struct
comedi_subdevice
*
s
,
110
struct
comedi_insn
*
insn
,
unsigned
int
*
data
)
111
{
112
unsigned
int
chan
=
CR_CHAN
(insn->
chanspec
);
113
unsigned
int
range
=
CR_RANGE
(insn->
chanspec
);
114
unsigned
int
val
;
115
unsigned
char
control
;
116
int
n
;
117
118
/*
119
* Setup the control byte for internal 2MHz clock, 3uS conversion,
120
* at the desired range of the requested channel.
121
*/
122
control =
AIO12_8_ADC_MODE_NORMAL
|
AIO12_8_ADC_ACQ_3USEC
|
123
AIO12_8_ADC_RANGE
(range) |
AIO12_8_ADC_CHAN
(chan);
124
125
/* Read status to clear EOC latch */
126
inb
(dev->
iobase
+
AIO12_8_STATUS_REG
);
127
128
for
(n = 0; n < insn->
n
; n++) {
129
int
timeout
= 5;
130
131
/* Setup and start conversion */
132
outb
(control, dev->
iobase
+
AIO12_8_ADC_REG
);
133
134
/* Wait for conversion to complete */
135
do
{
136
val =
inb
(dev->
iobase
+
AIO12_8_STATUS_REG
);
137
timeout--;
138
if
(timeout == 0) {
139
dev_err
(dev->
class_dev
,
"ADC timeout\n"
);
140
return
-
ETIMEDOUT
;
141
}
142
}
while
(!(val &
AIO12_8_STATUS_ADC_EOC
));
143
144
data[
n
] =
inw
(dev->
iobase
+
AIO12_8_ADC_REG
) & s->
maxdata
;
145
}
146
147
return
insn->
n
;
148
}
149
150
static
int
aio_aio12_8_ao_read(
struct
comedi_device
*
dev
,
151
struct
comedi_subdevice
*
s
,
152
struct
comedi_insn
*
insn
,
unsigned
int
*
data
)
153
{
154
struct
aio12_8_private
*
devpriv
= dev->
private
;
155
unsigned
int
chan
=
CR_CHAN
(insn->
chanspec
);
156
int
val
= devpriv->
ao_readback
[chan];
157
int
i
;
158
159
for
(i = 0; i < insn->
n
; i++)
160
data[i] = val;
161
return
insn->
n
;
162
}
163
164
static
int
aio_aio12_8_ao_write(
struct
comedi_device
*dev,
165
struct
comedi_subdevice
*s,
166
struct
comedi_insn
*insn,
unsigned
int
*data)
167
{
168
struct
aio12_8_private
*devpriv = dev->
private
;
169
unsigned
int
chan =
CR_CHAN
(insn->
chanspec
);
170
unsigned
long
port
= dev->
iobase
+
AIO12_8_DAC_REG
(chan);
171
unsigned
int
val = 0;
172
int
i
;
173
174
/* enable DACs */
175
outb
(
AIO12_8_DAC_ENABLE_REF_ENA
, dev->
iobase
+
AIO12_8_DAC_ENABLE_REG
);
176
177
for
(i = 0; i < insn->
n
; i++) {
178
val = data[
i
];
179
outw
(val, port);
180
}
181
182
devpriv->
ao_readback
[chan] =
val
;
183
184
return
insn->
n
;
185
}
186
187
static
const
struct
comedi_lrange
range_aio_aio12_8 = {
188
4,
189
{
190
UNI_RANGE
(5),
191
BIP_RANGE
(5),
192
UNI_RANGE
(10),
193
BIP_RANGE
(10),
194
}
195
};
196
197
static
int
aio_aio12_8_attach(
struct
comedi_device
*dev,
198
struct
comedi_devconfig
*it)
199
{
200
const
struct
aio12_8_boardtype
*
board
= comedi_board(dev);
201
struct
aio12_8_private
*
devpriv
;
202
struct
comedi_subdevice
*
s
;
203
int
iobase
;
204
int
ret
;
205
206
dev->
board_name
= board->
name
;
207
208
iobase = it->
options
[0];
209
if
(!
request_region
(iobase, 32, dev->
board_name
)) {
210
printk
(
KERN_ERR
"I/O port conflict"
);
211
return
-
EIO
;
212
}
213
dev->
iobase
=
iobase
;
214
215
ret = alloc_private(dev,
sizeof
(*devpriv));
216
if
(ret)
217
return
ret
;
218
devpriv = dev->
private
;
219
220
ret =
comedi_alloc_subdevices
(dev, 4);
221
if
(ret)
222
return
ret
;
223
224
s = &dev->
subdevices
[0];
225
if
(board->
ai_nchan
) {
226
/* Analog input subdevice */
227
s->
type
=
COMEDI_SUBD_AI
;
228
s->
subdev_flags
=
SDF_READABLE
|
SDF_GROUND
|
SDF_DIFF
;
229
s->
n_chan
= board->
ai_nchan
;
230
s->
maxdata
= 0x0fff;
231
s->
range_table
= &range_aio_aio12_8;
232
s->
insn_read
= aio_aio12_8_ai_read;
233
}
else
{
234
s->
type
=
COMEDI_SUBD_UNUSED
;
235
}
236
237
s = &dev->
subdevices
[1];
238
if
(board->
ao_nchan
) {
239
/* Analog output subdevice */
240
s->
type
=
COMEDI_SUBD_AO
;
241
s->
subdev_flags
=
SDF_WRITABLE
|
SDF_GROUND
|
SDF_DIFF
;
242
s->
n_chan
= 4;
243
s->
maxdata
= 0x0fff;
244
s->
range_table
= &range_aio_aio12_8;
245
s->
insn_read
= aio_aio12_8_ao_read;
246
s->
insn_write
= aio_aio12_8_ao_write;
247
}
else
{
248
s->
type
=
COMEDI_SUBD_UNUSED
;
249
}
250
251
s = &dev->
subdevices
[2];
252
/* 8255 Digital i/o subdevice */
253
iobase = dev->
iobase
+
AIO12_8_8255_BASE_REG
;
254
ret =
subdev_8255_init
(dev, s,
NULL
, iobase);
255
if
(ret)
256
return
ret
;
257
258
s = &dev->
subdevices
[3];
259
/* 8254 counter/timer subdevice */
260
s->
type
=
COMEDI_SUBD_UNUSED
;
261
262
dev_info
(dev->
class_dev
,
"%s: %s attached\n"
,
263
dev->
driver
->driver_name, dev->
board_name
);
264
265
return
0;
266
}
267
268
static
void
aio_aio12_8_detach(
struct
comedi_device
*dev)
269
{
270
if
(dev->
subdevices
)
271
subdev_8255_cleanup
(dev, &dev->
subdevices
[2]);
272
if
(dev->
iobase
)
273
release_region
(dev->
iobase
, 24);
274
}
275
276
static
struct
comedi_driver
aio_aio12_8_driver = {
277
.driver_name =
"aio_aio12_8"
,
278
.module =
THIS_MODULE
,
279
.attach = aio_aio12_8_attach,
280
.detach = aio_aio12_8_detach,
281
.board_name = &board_types[0].
name
,
282
.num_names =
ARRAY_SIZE
(board_types),
283
.offset =
sizeof
(
struct
aio12_8_boardtype
),
284
};
285
module_comedi_driver
(aio_aio12_8_driver);
286
287
MODULE_AUTHOR
(
"Comedi http://www.comedi.org"
);
288
MODULE_DESCRIPTION
(
"Comedi low-level driver"
);
289
MODULE_LICENSE
(
"GPL"
);
Generated on Thu Jan 10 2013 14:26:38 for Linux Kernel by
1.8.2