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
pcmad.c
Go to the documentation of this file.
1
/*
2
comedi/drivers/pcmad.c
3
Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16
4
5
COMEDI - Linux Control and Measurement Device Interface
6
Copyright (C) 2000,2001 David A. Schleef <
[email protected]
>
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
Driver: pcmad
25
Description: Winsystems PCM-A/D12, PCM-A/D16
26
Author: ds
27
Devices: [Winsystems] PCM-A/D12 (pcmad12), PCM-A/D16 (pcmad16)
28
Status: untested
29
30
This driver was written on a bet that I couldn't write a driver
31
in less than 2 hours. I won the bet, but never got paid. =(
32
33
Configuration options:
34
[0] - I/O port base
35
[1] - unused
36
[2] - Analog input reference
37
0 = single ended
38
1 = differential
39
[3] - Analog input encoding (must match jumpers)
40
0 = straight binary
41
1 = two's complement
42
*/
43
44
#include <
linux/interrupt.h
>
45
#include "../comedidev.h"
46
47
#include <
linux/ioport.h
>
48
49
#define PCMAD_SIZE 4
50
51
#define PCMAD_STATUS 0
52
#define PCMAD_LSB 1
53
#define PCMAD_MSB 2
54
#define PCMAD_CONVERT 1
55
56
struct
pcmad_board_struct
{
57
const
char
*
name
;
58
int
n_ai_bits
;
59
};
60
61
struct
pcmad_priv_struct
{
62
int
differential
;
63
int
twos_comp
;
64
};
65
#define devpriv ((struct pcmad_priv_struct *)dev->private)
66
67
#define TIMEOUT 100
68
69
static
int
pcmad_ai_insn_read(
struct
comedi_device
*
dev
,
70
struct
comedi_subdevice
*
s
,
71
struct
comedi_insn
*
insn
,
unsigned
int
*
data
)
72
{
73
const
struct
pcmad_board_struct
*
board
= comedi_board(dev);
74
int
i
;
75
int
chan
;
76
int
n
;
77
78
chan =
CR_CHAN
(insn->
chanspec
);
79
80
for
(n = 0; n < insn->
n
; n++) {
81
outb
(chan, dev->
iobase
+
PCMAD_CONVERT
);
82
83
for
(i = 0; i <
TIMEOUT
; i++) {
84
if
((
inb
(dev->
iobase
+
PCMAD_STATUS
) & 0x3) == 0x3)
85
break
;
86
}
87
data[
n
] =
inb
(dev->
iobase
+
PCMAD_LSB
);
88
data[
n
] |= (
inb
(dev->
iobase
+
PCMAD_MSB
) << 8);
89
90
if
(
devpriv
->twos_comp)
91
data[
n
] ^= (1 << (board->
n_ai_bits
- 1));
92
}
93
94
return
n
;
95
}
96
97
/*
98
* options:
99
* 0 i/o base
100
* 1 unused
101
* 2 0=single ended 1=differential
102
* 3 0=straight binary 1=two's comp
103
*/
104
static
int
pcmad_attach(
struct
comedi_device
*
dev
,
struct
comedi_devconfig
*it)
105
{
106
const
struct
pcmad_board_struct
*
board
= comedi_board(dev);
107
int
ret
;
108
struct
comedi_subdevice
*
s
;
109
unsigned
long
iobase
;
110
111
iobase = it->
options
[0];
112
printk
(
KERN_INFO
"comedi%d: pcmad: 0x%04lx "
, dev->
minor
, iobase);
113
if
(!
request_region
(iobase,
PCMAD_SIZE
,
"pcmad"
)) {
114
printk
(
KERN_CONT
"I/O port conflict\n"
);
115
return
-
EIO
;
116
}
117
printk
(
KERN_CONT
"\n"
);
118
dev->
iobase
=
iobase
;
119
120
ret =
comedi_alloc_subdevices
(dev, 1);
121
if
(ret)
122
return
ret
;
123
124
ret = alloc_private(dev,
sizeof
(
struct
pcmad_priv_struct
));
125
if
(ret < 0)
126
return
ret
;
127
128
dev->
board_name
= board->
name
;
129
130
s = &dev->
subdevices
[0];
131
s->
type
=
COMEDI_SUBD_AI
;
132
s->
subdev_flags
=
SDF_READABLE
|
AREF_GROUND
;
133
s->
n_chan
= 16;
/* XXX */
134
s->
len_chanlist
= 1;
135
s->
insn_read
= pcmad_ai_insn_read;
136
s->
maxdata
= (1 << board->
n_ai_bits
) - 1;
137
s->
range_table
= &
range_unknown
;
138
139
return
0;
140
}
141
142
static
void
pcmad_detach(
struct
comedi_device
*dev)
143
{
144
if
(dev->
irq
)
145
free_irq
(dev->
irq
, dev);
146
if
(dev->
iobase
)
147
release_region
(dev->
iobase
,
PCMAD_SIZE
);
148
}
149
150
static
const
struct
pcmad_board_struct
pcmad_boards[] = {
151
{
152
.name =
"pcmad12"
,
153
.n_ai_bits = 12,
154
}, {
155
.name =
"pcmad16"
,
156
.n_ai_bits = 16,
157
},
158
};
159
static
struct
comedi_driver
pcmad_driver = {
160
.driver_name =
"pcmad"
,
161
.module =
THIS_MODULE
,
162
.attach = pcmad_attach,
163
.detach = pcmad_detach,
164
.board_name = &pcmad_boards[0].
name
,
165
.num_names =
ARRAY_SIZE
(pcmad_boards),
166
.offset =
sizeof
(pcmad_boards[0]),
167
};
168
module_comedi_driver
(pcmad_driver);
169
170
MODULE_AUTHOR
(
"Comedi http://www.comedi.org"
);
171
MODULE_DESCRIPTION
(
"Comedi low-level driver"
);
172
MODULE_LICENSE
(
"GPL"
);
Generated on Thu Jan 10 2013 14:27:20 for Linux Kernel by
1.8.2