openocd: fix simple cases of Yoda condition
[fw/openocd] / src / pld / pld.c
1 /***************************************************************************
2  *   Copyright (C) 2006 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "pld.h"
24 #include <helper/log.h>
25 #include <helper/replacements.h>
26 #include <helper/time_support.h>
27
28
29 /* pld drivers
30  */
31 extern struct pld_driver virtex2_pld;
32
33 static struct pld_driver *pld_drivers[] = {
34         &virtex2_pld,
35         NULL,
36 };
37
38 static struct pld_device *pld_devices;
39
40 struct pld_device *get_pld_device_by_num(int num)
41 {
42         struct pld_device *p;
43         int i = 0;
44
45         for (p = pld_devices; p; p = p->next) {
46                 if (i++ == num)
47                         return p;
48         }
49
50         return NULL;
51 }
52
53 /* pld device <driver> [driver_options ...]
54  */
55 COMMAND_HANDLER(handle_pld_device_command)
56 {
57         int i;
58         int found = 0;
59
60         if (CMD_ARGC < 1)
61                 return ERROR_COMMAND_SYNTAX_ERROR;
62
63         for (i = 0; pld_drivers[i]; i++) {
64                 if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) {
65                         struct pld_device *p, *c;
66
67                         /* register pld specific commands */
68                         int retval;
69                         if (pld_drivers[i]->commands) {
70                                 retval = register_commands(CMD_CTX, NULL,
71                                                 pld_drivers[i]->commands);
72                                 if (retval != ERROR_OK) {
73                                         LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
74                                         return ERROR_FAIL;
75                                 }
76                         }
77
78                         c = malloc(sizeof(struct pld_device));
79                         c->driver = pld_drivers[i];
80                         c->next = NULL;
81
82                         retval = CALL_COMMAND_HANDLER(
83                                         pld_drivers[i]->pld_device_command, c);
84                         if (retval != ERROR_OK) {
85                                 LOG_ERROR("'%s' driver rejected pld device",
86                                         CMD_ARGV[0]);
87                                 free(c);
88                                 return ERROR_OK;
89                         }
90
91                         /* put pld device in linked list */
92                         if (pld_devices) {
93                                 /* find last pld device */
94                                 for (p = pld_devices; p && p->next; p = p->next)
95                                         ;
96                                 if (p)
97                                         p->next = c;
98                         } else
99                                 pld_devices = c;
100
101                         found = 1;
102                 }
103         }
104
105         /* no matching pld driver found */
106         if (!found) {
107                 LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
108                 exit(-1);
109         }
110
111         return ERROR_OK;
112 }
113
114 COMMAND_HANDLER(handle_pld_devices_command)
115 {
116         struct pld_device *p;
117         int i = 0;
118
119         if (!pld_devices) {
120                 command_print(CMD, "no pld devices configured");
121                 return ERROR_OK;
122         }
123
124         for (p = pld_devices; p; p = p->next)
125                 command_print(CMD, "#%i: %s", i++, p->driver->name);
126
127         return ERROR_OK;
128 }
129
130 COMMAND_HANDLER(handle_pld_load_command)
131 {
132         int retval;
133         struct timeval start, end, duration;
134         struct pld_device *p;
135
136         gettimeofday(&start, NULL);
137
138         if (CMD_ARGC < 2)
139                 return ERROR_COMMAND_SYNTAX_ERROR;
140
141         unsigned dev_id;
142         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
143         p = get_pld_device_by_num(dev_id);
144         if (!p) {
145                 command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
146                 return ERROR_OK;
147         }
148
149         retval = p->driver->load(p, CMD_ARGV[1]);
150         if (retval != ERROR_OK) {
151                 command_print(CMD, "failed loading file %s to pld device %u",
152                         CMD_ARGV[1], dev_id);
153                 switch (retval) {
154                 }
155                 return retval;
156         } else {
157                 gettimeofday(&end, NULL);
158                 timeval_subtract(&duration, &end, &start);
159
160                 command_print(CMD, "loaded file %s to pld device %u in %jis %jius",
161                         CMD_ARGV[1], dev_id,
162                         (intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
163         }
164
165         return ERROR_OK;
166 }
167
168 static const struct command_registration pld_exec_command_handlers[] = {
169         {
170                 .name = "devices",
171                 .handler = handle_pld_devices_command,
172                 .mode = COMMAND_EXEC,
173                 .help = "list configured pld devices",
174                 .usage = "",
175         },
176         {
177                 .name = "load",
178                 .handler = handle_pld_load_command,
179                 .mode = COMMAND_EXEC,
180                 .help = "load configuration file into PLD",
181                 .usage = "pld_num filename",
182         },
183         COMMAND_REGISTRATION_DONE
184 };
185
186 static int pld_init(struct command_context *cmd_ctx)
187 {
188         if (!pld_devices)
189                 return ERROR_OK;
190
191         return register_commands(cmd_ctx, "pld", pld_exec_command_handlers);
192 }
193
194 COMMAND_HANDLER(handle_pld_init_command)
195 {
196         if (CMD_ARGC != 0)
197                 return ERROR_COMMAND_SYNTAX_ERROR;
198
199         static bool pld_initialized;
200         if (pld_initialized) {
201                 LOG_INFO("'pld init' has already been called");
202                 return ERROR_OK;
203         }
204         pld_initialized = true;
205
206         LOG_DEBUG("Initializing PLDs...");
207         return pld_init(CMD_CTX);
208 }
209
210 static const struct command_registration pld_config_command_handlers[] = {
211         {
212                 .name = "device",
213                 .mode = COMMAND_CONFIG,
214                 .handler = handle_pld_device_command,
215                 .help = "configure a PLD device",
216                 .usage = "driver_name [driver_args ... ]",
217         },
218         {
219                 .name = "init",
220                 .mode = COMMAND_CONFIG,
221                 .handler = handle_pld_init_command,
222                 .help = "initialize PLD devices",
223                 .usage = ""
224         },
225         COMMAND_REGISTRATION_DONE
226 };
227 static const struct command_registration pld_command_handler[] = {
228         {
229                 .name = "pld",
230                 .mode = COMMAND_ANY,
231                 .help = "programmable logic device commands",
232                 .usage = "",
233                 .chain = pld_config_command_handlers,
234         },
235         COMMAND_REGISTRATION_DONE
236 };
237 int pld_register_commands(struct command_context *cmd_ctx)
238 {
239         return register_commands(cmd_ctx, NULL, pld_command_handler);
240 }