vmod/vmodttl: fixed bug related to luns not ordered and/or not starting from zero.
[ht-drivers.git] / vmod / lib / libvmodttl.c
blobf9a3da9939c777794394bde46abd8a82707f2038
1 /*-
2 * Copyright (c) 2010 Samuel I. Gonsalvez <siglesia@cern.ch>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <sys/ioctl.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include "cio8536.h"
39 #include "vmodttl.h"
40 #include "libvmodttl.h"
42 #define DEV_NAME 20
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] = "";
52 int ret;
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);
61 if(ret < 0){
62 fprintf(stderr, "libvmodttl: Failed to open the file: %s\n", strerror(errno));
63 fprintf(stderr, "libvmodttl: Device /dev/vmodttl%d\n", lun);
64 return -1;
67 luns_to_fd[lun] = ret;
68 return 0;
71 int vmodttl_close(int lun)
73 int ret;
75 ret = close(luns_to_fd[lun]);
76 luns_to_fd[lun] = 0;
77 return ret;
80 int vmodttl_write(int lun, enum vmodttl_channel chan, int val)
82 struct vmodttlarg buf;
83 int ret = 0;
85 buf.dev = chan;
86 buf.val = val;
88 ret = ioctl(luns_to_fd[lun], VMODTTL_WRITE_CHAN, (char *)&buf);
90 if(ret){
91 fprintf(stderr,"libvmodttl: Failed to put data to channel %d: %s", chan, strerror(errno));
92 return -1;
95 return 0;
98 int vmodttl_read(int lun, enum vmodttl_channel chan, int *val)
100 struct vmodttlarg buf;
101 int ret = 0;
103 buf.dev = chan;
104 buf.val = 0;
106 ret = ioctl(luns_to_fd[lun], VMODTTL_READ_CHAN, (char *)&buf);
108 if(ret){
109 fprintf(stderr, "libvmodttl: Failed to get data from channel %d: %s", chan, strerror(errno));
110 return -1;
112 if (chan == VMOD_TTL_CHANNELS_AB)
113 *val = buf.val & 0xffff;
114 else
115 *val = buf.val & 0x00ff;
117 return 0;
120 int vmodttl_io_config(int lun, struct vmodttl_config conf)
122 int i;
123 struct vmodttlconfig ttl_conf;
124 int fd, ret = 0;
125 int io_config = 0;
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);
143 if(ret < 0){
144 fprintf(stderr, "libvmodttl: Failed to change the I/O configuration of the channels: %s\n", strerror(errno));
145 return ret;
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]);
156 return 0;
159 int vmodttl_io_chan_config(int lun, enum vmodttl_channel chan, struct vmodttl_config conf)
161 struct vmodttl_config ttl_conf;
162 int fd, i;
164 vmodttl_read_config(lun, &ttl_conf);
165 fd = luns_to_fd[lun];
167 switch(chan) {
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];
174 break;
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];
182 break;
183 case VMOD_TTL_CHANNELS_AB:
184 ttl_conf = conf;
185 break;
186 default:
188 fprintf(stderr, "libvmodttl: Invalid channel (%d) to configure.\n", chan);
189 return -1;
193 return vmodttl_io_config(lun, ttl_conf);
196 int vmodttl_read_config(int lun, struct vmodttl_config *conf)
198 int ret;
199 int fd;
200 int i;
201 struct vmodttlconfig ttl_conf;
203 fd = luns_to_fd[lun];
204 ret = ioctl(fd, VMODTTL_READ_CONFIG, (char *)&ttl_conf);
206 if(ret < 0)
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);
227 return ret;
230 int vmodttl_read_device(int lun, unsigned char buffer[2])
232 return 0;
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)
240 *bit_pattern = ANY;
241 else if (pmr == 1 && ptr == 0 && ppr == 0)
242 *bit_pattern = ZERO;
243 else if (pmr == 1 && ptr == 0 && ppr == 1)
244 *bit_pattern = ONE;
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;
249 else
250 *bit_pattern = OFF;
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) {
259 case ANY:
260 *pmr = 0;
261 *ptr = 1;
262 *ppr = 0;
263 break;
264 case ZERO:
265 *pmr = 1;
266 *ptr = 0;
267 *ppr = 0;
268 break;
270 case ONE:
271 *pmr = 1;
272 *ptr = 0;
273 *ppr = 1;
274 break;
276 case ONE_TO_ZERO:
277 *pmr = 1;
278 *ptr = 1;
279 *ppr = 0;
280 break;
282 case ZERO_TO_ONE:
283 *pmr = 1;
284 *ptr = 1;
285 *ppr = 1;
286 break;
288 case OFF:
289 default:
290 *pmr = 0;
291 *ptr = 0;
292 *ppr = 0;
296 int vmodttl_pattern(int lun, enum vmodttl_channel port, int pos, enum vmodttl_conf_pattern bit_pattern)
298 struct vmodttl_pattern buf;
299 int ret = 0;
301 if(port < VMOD_TTL_CHANNEL_A || port > VMOD_TTL_CHANNEL_B) {
302 fprintf(stderr, "libvmodttl: Wrong channel to configure the pattern\n");
303 return -1;
306 if(pos < 0 || pos >= NUM_BITS) {
307 fprintf(stderr, "libvmodttl: Wrong bit position to configure the pattern\n");
308 return -1;
311 vmodttl_get_bit_pattern(bit_pattern, &buf.pmr, &buf.ptr, &buf.ppr);
312 buf.port = port;
313 buf.pos = pos;
315 ret = ioctl(luns_to_fd[lun], VMODTTL_PATTERN, (char *)&buf);
317 if(ret){
318 fprintf(stderr, "libvmodttl: Failed to configure the pattern to the channel %d bit %d: %s",
319 port, pos, strerror(errno));
320 return -1;
323 return 0;