2 * Copyright (c) 2010 Samuel I. Gonsalvez <siglesia@cern.ch>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/ioctl.h>
35 #include <sys/types.h>
40 #include "libvmodttl.h"
44 static int luns_to_fd
[VMODTTL_MAX_BOARDS
];
46 static void vmodttl_get_from_bit_pattern(enum vmodttl_conf_pattern
*bit_pattern
, unsigned char pmr
,
47 unsigned char ptr
, unsigned char ppr
);
49 int vmodttl_open(int lun
)
51 char device
[DEV_NAME
] = "";
54 if (luns_to_fd
[lun
] != 0)
55 return luns_to_fd
[lun
];
57 sprintf(device
, "/dev/vmodttl.%d", lun
);
59 ret
= open(device
, O_RDWR
, 0);
62 fprintf(stderr
, "libvmodttl: Failed to open the file: %s\n", strerror(errno
));
63 fprintf(stderr
, "libvmodttl: Device /dev/vmodttl%d\n", lun
);
67 luns_to_fd
[lun
] = ret
;
71 int vmodttl_close(int lun
)
75 ret
= close(luns_to_fd
[lun
]);
80 int vmodttl_write(int lun
, enum vmodttl_channel chan
, int val
)
82 struct vmodttlarg buf
;
88 ret
= ioctl(luns_to_fd
[lun
], VMODTTL_WRITE_CHAN
, (char *)&buf
);
91 fprintf(stderr
,"libvmodttl: Failed to put data to channel %d: %s", chan
, strerror(errno
));
98 int vmodttl_read(int lun
, enum vmodttl_channel chan
, int *val
)
100 struct vmodttlarg buf
;
106 ret
= ioctl(luns_to_fd
[lun
], VMODTTL_READ_CHAN
, (char *)&buf
);
109 fprintf(stderr
, "libvmodttl: Failed to get data from channel %d: %s", chan
, strerror(errno
));
112 if (chan
== VMOD_TTL_CHANNELS_AB
)
113 *val
= buf
.val
& 0xffff;
115 *val
= buf
.val
& 0x00ff;
120 int vmodttl_io_config(int lun
, struct vmodttl_config conf
)
123 struct vmodttlconfig ttl_conf
;
127 fd
= luns_to_fd
[lun
];
128 io_config
= conf
.dir_a
& 0x01;
129 io_config
+= (conf
.dir_b
& 0x01) << 1;
131 ttl_conf
.io_flag
= io_config
;
132 ttl_conf
.us_pulse
= conf
.us_pulse
;
133 ttl_conf
.invert
= conf
.inverting_logic
;
135 ttl_conf
.open_collector
= conf
.mode_a
;
136 ttl_conf
.open_collector
+= (conf
.mode_b
& 0x01) << 1;
137 ttl_conf
.open_collector
+= (conf
.mode_c
& 0x01) << 2;
139 ttl_conf
.pattern_mode_a
= conf
.pattern_mode_a
;
140 ttl_conf
.pattern_mode_b
= conf
.pattern_mode_b
;
142 ret
= ioctl(fd
, VMODTTL_CONFIG
, (char *)&ttl_conf
);
144 fprintf(stderr
, "libvmodttl: Failed to change the I/O configuration of the channels: %s\n", strerror(errno
));
148 /* After configured the device, we configure the pattern */
149 for(i
= 0; i
< NR_BITS
; i
++) {
150 if (conf
.dir_a
== CHAN_IN
)
151 vmodttl_pattern(lun
, CHAN_A
, i
, conf
.conf_pattern_a
[i
]);
152 if (conf
.dir_b
== CHAN_IN
)
153 vmodttl_pattern(lun
, CHAN_B
, i
, conf
.conf_pattern_a
[i
]);
159 int vmodttl_io_chan_config(int lun
, enum vmodttl_channel chan
, struct vmodttl_config conf
)
161 struct vmodttl_config ttl_conf
;
164 vmodttl_read_config(lun
, &ttl_conf
);
165 fd
= luns_to_fd
[lun
];
168 case VMOD_TTL_CHANNEL_A
:
169 ttl_conf
.dir_a
= conf
.dir_a
;
170 ttl_conf
.mode_a
= conf
.mode_a
;
171 ttl_conf
.pattern_mode_a
= conf
.pattern_mode_a
;
172 for(i
= 0; i
< NR_BITS
; i
++)
173 ttl_conf
.conf_pattern_a
[i
] = conf
.conf_pattern_a
[i
];
175 case VMOD_TTL_CHANNEL_B
:
176 ttl_conf
.dir_b
= conf
.dir_b
;
177 ttl_conf
.mode_b
= conf
.mode_b
;
178 ttl_conf
.pattern_mode_b
= conf
.pattern_mode_b
;
179 for(i
= 0; i
< NR_BITS
; i
++)
180 ttl_conf
.conf_pattern_b
[i
] = conf
.conf_pattern_b
[i
];
183 case VMOD_TTL_CHANNELS_AB
:
188 fprintf(stderr
, "libvmodttl: Invalid channel (%d) to configure.\n", chan
);
193 return vmodttl_io_config(lun
, ttl_conf
);
196 int vmodttl_read_config(int lun
, struct vmodttl_config
*conf
)
201 struct vmodttlconfig ttl_conf
;
203 fd
= luns_to_fd
[lun
];
204 ret
= ioctl(fd
, VMODTTL_READ_CONFIG
, (char *)&ttl_conf
);
207 fprintf(stderr
, "libvmodttl: Failed to copy the I/O configuration of the channels: %s\n", strerror(errno
));
209 conf
->dir_a
= ttl_conf
.io_flag
& 0x01;
210 conf
->dir_b
= (ttl_conf
.io_flag
>> 1) & 0x01;
211 conf
->mode_a
= ttl_conf
.open_collector
& 0x01;
212 conf
->mode_b
= (ttl_conf
.open_collector
>> 1) & 0x01;
213 conf
->mode_c
= (ttl_conf
.open_collector
>> 2) & 0x01;
214 conf
->inverting_logic
= ttl_conf
.invert
;
215 conf
->us_pulse
= ttl_conf
.us_pulse
;
216 conf
->pattern_mode_a
= ttl_conf
.pattern_mode_a
;
217 conf
->pattern_mode_b
= ttl_conf
.pattern_mode_b
;
219 for(i
= 0; i
< NR_BITS
; i
++) {
220 struct vmodttl_pattern
*pattern
= &ttl_conf
.bit_pattern_a
[i
];
221 vmodttl_get_from_bit_pattern(&conf
->conf_pattern_a
[i
],
222 pattern
->pmr
, pattern
->ptr
, pattern
->ppr
);
223 pattern
= &ttl_conf
.bit_pattern_b
[i
];
224 vmodttl_get_from_bit_pattern(&conf
->conf_pattern_b
[i
],
225 pattern
->pmr
, pattern
->ptr
, pattern
->ppr
);
230 int vmodttl_read_device(int lun
, unsigned char buffer
[2])
235 static void vmodttl_get_from_bit_pattern(enum vmodttl_conf_pattern
*bit_pattern
, unsigned char pmr
,
236 unsigned char ptr
, unsigned char ppr
)
239 if (pmr
== 0 && ptr
== 1 && ppr
== 0)
241 else if (pmr
== 1 && ptr
== 0 && ppr
== 0)
243 else if (pmr
== 1 && ptr
== 0 && ppr
== 1)
245 else if (pmr
== 1 && ptr
== 1 && ppr
== 0)
246 *bit_pattern
= ONE_TO_ZERO
;
247 else if (pmr
== 1 && ptr
== 1 && ppr
== 1)
248 *bit_pattern
= ZERO_TO_ONE
;
254 static void vmodttl_get_bit_pattern(enum vmodttl_conf_pattern bit_pattern
, unsigned char *pmr
,
255 unsigned char *ptr
, unsigned char *ppr
)
257 switch(bit_pattern
) {
296 int vmodttl_pattern(int lun
, enum vmodttl_channel port
, int pos
, enum vmodttl_conf_pattern bit_pattern
)
298 struct vmodttl_pattern buf
;
301 if(port
< VMOD_TTL_CHANNEL_A
|| port
> VMOD_TTL_CHANNEL_B
) {
302 fprintf(stderr
, "libvmodttl: Wrong channel to configure the pattern\n");
306 if(pos
< 0 || pos
>= NUM_BITS
) {
307 fprintf(stderr
, "libvmodttl: Wrong bit position to configure the pattern\n");
311 vmodttl_get_bit_pattern(bit_pattern
, &buf
.pmr
, &buf
.ptr
, &buf
.ppr
);
315 ret
= ioctl(luns_to_fd
[lun
], VMODTTL_PATTERN
, (char *)&buf
);
318 fprintf(stderr
, "libvmodttl: Failed to configure the pattern to the channel %d bit %d: %s",
319 port
, pos
, strerror(errno
));