1 /*
2 * avrdude - A Downloader/Uploader for AVR device programmers
3 * Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /* $Id: ppi.c 1321 2014-06-13 20:07:40Z awachtler $ */
20
21
22 #if !defined(WIN32NATIVE)
23
24 #include "ac_cfg.h"
25
26 #if HAVE_PARPORT
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <errno.h>
34
35 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
36 # include "freebsd_ppi.h"
37 #elif defined(__linux__)
38 # include "linux_ppdev.h"
39 #elif defined(__sun__) || defined(__sun) /* Solaris */
40 # include "solaris_ecpp.h"
41 #endif
42
43 #include "avrdude.h"
44 #include "libavrdude.h"
45
46 #include "ppi.h"
47
48 enum {
49 PPI_READ,
50 PPI_WRITE,
51 PPI_SHADOWREAD
52 };
53
ppi_shadow_access(union filedescriptor * fdp,int reg,unsigned char * v,unsigned char action)54 static int ppi_shadow_access(union filedescriptor *fdp, int reg,
55 unsigned char *v, unsigned char action)
56 {
57 static unsigned char shadow[3];
58 int shadow_num;
59
60 switch (reg) {
61 case PPIDATA:
62 shadow_num = 0;
63 break;
64 case PPICTRL:
65 shadow_num = 1;
66 break;
67 case PPISTATUS:
68 shadow_num = 2;
69 break;
70 default:
71 avrdude_message(MSG_INFO, "%s: avr_set(): invalid register=%d\n",
72 progname, reg);
73 return -1;
74 break;
75 }
76
77 switch (action) {
78 case PPI_SHADOWREAD:
79 *v = shadow[shadow_num];
80 break;
81 case PPI_READ:
82 DO_PPI_READ(fdp->ifd, reg, v);
83 shadow[shadow_num]=*v;
84 break;
85 case PPI_WRITE:
86 shadow[shadow_num]=*v;
87 DO_PPI_WRITE(fdp->ifd, reg, v);
88 break;
89 }
90 return 0;
91 }
92
93 /*
94 * set the indicated bit of the specified register.
95 */
ppi_set(union filedescriptor * fdp,int reg,int bit)96 int ppi_set(union filedescriptor *fdp, int reg, int bit)
97 {
98 unsigned char v;
99 int rc;
100
101 rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD);
102 v |= bit;
103 rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
104
105 if (rc)
106 return -1;
107
108 return 0;
109 }
110
111
112 /*
113 * clear the indicated bit of the specified register.
114 */
ppi_clr(union filedescriptor * fdp,int reg,int bit)115 int ppi_clr(union filedescriptor *fdp, int reg, int bit)
116 {
117 unsigned char v;
118 int rc;
119
120 rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD);
121 v &= ~bit;
122 rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
123
124 if (rc)
125 return -1;
126
127 return 0;
128 }
129
130
131 /*
132 * get the indicated bit of the specified register.
133 */
ppi_get(union filedescriptor * fdp,int reg,int bit)134 int ppi_get(union filedescriptor *fdp, int reg, int bit)
135 {
136 unsigned char v;
137 int rc;
138
139 rc = ppi_shadow_access(fdp, reg, &v, PPI_READ);
140 v &= bit;
141
142 if (rc)
143 return -1;
144
145 return v; /* v == bit */
146 }
147
148 /*
149 * toggle the indicated bit of the specified register.
150 */
ppi_toggle(union filedescriptor * fdp,int reg,int bit)151 int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
152 {
153 unsigned char v;
154 int rc;
155
156 rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD);
157 v ^= bit;
158 rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
159
160 if (rc)
161 return -1;
162
163 return 0;
164 }
165
166
167 /*
168 * get all bits of the specified register.
169 */
ppi_getall(union filedescriptor * fdp,int reg)170 int ppi_getall(union filedescriptor *fdp, int reg)
171 {
172 unsigned char v;
173 int rc;
174
175 rc = ppi_shadow_access(fdp, reg, &v, PPI_READ);
176
177 if (rc)
178 return -1;
179
180 return v; /* v == bit */
181 }
182
183 /*
184 * set all bits of the specified register to val.
185 */
ppi_setall(union filedescriptor * fdp,int reg,int val)186 int ppi_setall(union filedescriptor *fdp, int reg, int val)
187 {
188 unsigned char v;
189 int rc;
190
191 v = val;
192 rc = ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
193
194 if (rc)
195 return -1;
196
197 return 0;
198 }
199
200
ppi_open(char * port,union filedescriptor * fdp)201 void ppi_open(char * port, union filedescriptor *fdp)
202 {
203 int fd;
204 unsigned char v;
205
206 fd = open(port, O_RDWR);
207 if (fd < 0) {
208 avrdude_message(MSG_INFO, "%s: can't open device \"%s\": %s\n",
209 progname, port, strerror(errno));
210 fdp->ifd = -1;
211 return;
212 }
213
214 ppi_claim (fd);
215
216 /*
217 * Initialize shadow registers
218 */
219
220 ppi_shadow_access (fdp, PPIDATA, &v, PPI_READ);
221 ppi_shadow_access (fdp, PPICTRL, &v, PPI_READ);
222 ppi_shadow_access (fdp, PPISTATUS, &v, PPI_READ);
223
224 fdp->ifd = fd;
225 }
226
227
ppi_close(union filedescriptor * fdp)228 void ppi_close(union filedescriptor *fdp)
229 {
230 ppi_release (fdp->ifd);
231 close(fdp->ifd);
232 }
233
234 #endif /* HAVE_PARPORT */
235
236 #endif /* !WIN32NATIVE */
237