pld: give devices a name for referencing in scripts
[openocd.git] / src / pld / pld.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2006 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "pld.h"
13 #include <sys/stat.h>
14 #include <helper/log.h>
15 #include <helper/replacements.h>
16 #include <helper/time_support.h>
17
18
19 static struct pld_driver *pld_drivers[] = {
20 &efinix_pld,
21 &gatemate_pld,
22 &gowin_pld,
23 &intel_pld,
24 &lattice_pld,
25 &virtex2_pld,
26 NULL,
27 };
28
29 static struct pld_device *pld_devices;
30
31 struct pld_device *get_pld_device_by_num(int num)
32 {
33 struct pld_device *p;
34 int i = 0;
35
36 for (p = pld_devices; p; p = p->next) {
37 if (i++ == num) {
38 LOG_WARNING("DEPRECATED: use pld name \"%s\" instead of number %d", p->name, num);
39 return p;
40 }
41 }
42
43 return NULL;
44 }
45
46 struct pld_device *get_pld_device_by_name(const char *name)
47 {
48 for (struct pld_device *p = pld_devices; p; p = p->next) {
49 if (strcmp(p->name, name) == 0)
50 return p;
51 }
52
53 return NULL;
54 }
55
56 struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
57 {
58 struct pld_device *dev = get_pld_device_by_name(str);
59 if (dev)
60 return dev;
61
62 char *end;
63 unsigned long dev_num = strtoul(str, &end, 0);
64 if (*end || dev_num > INT_MAX) {
65 LOG_ERROR("Invalid argument");
66 return NULL;
67 }
68
69 return get_pld_device_by_num(dev_num);
70 }
71
72 /* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options]
73 */
74 COMMAND_HANDLER(handle_pld_create_command)
75 {
76 if (CMD_ARGC < 2)
77 return ERROR_COMMAND_SYNTAX_ERROR;
78
79 struct pld_driver *pld_driver = NULL;
80
81 for (int i = 0; pld_drivers[i]; i++) {
82 if (strcmp(CMD_ARGV[1], pld_drivers[i]->name) == 0) {
83 pld_driver = pld_drivers[i];
84 break;
85 }
86 }
87
88 if (!pld_driver) {
89 LOG_ERROR("pld driver '%s' not found", CMD_ARGV[1]);
90 return ERROR_FAIL; /* exit(-1); */
91 }
92
93 if (get_pld_device_by_name(CMD_ARGV[0])) {
94 LOG_ERROR("pld device with name '%s' already exists", CMD_ARGV[0]);
95 return ERROR_FAIL;
96 }
97
98 struct pld_device *pld_device = malloc(sizeof(struct pld_device));
99 if (!pld_device) {
100 LOG_ERROR("Out of memory");
101 return ERROR_FAIL;
102 }
103
104 pld_device->driver = pld_driver;
105 pld_device->next = NULL;
106
107 int retval = CALL_COMMAND_HANDLER(pld_driver->pld_create_command, pld_device);
108 if (retval != ERROR_OK) {
109 LOG_ERROR("'%s' driver rejected pld device",
110 CMD_ARGV[1]);
111 free(pld_device);
112 return ERROR_OK;
113 }
114 pld_device->name = strdup(CMD_ARGV[0]);
115 if (!pld_device->name) {
116 LOG_ERROR("Out of memory");
117 free(pld_device);
118 return ERROR_FAIL;
119 }
120
121 /* register pld specific commands */
122 if (pld_driver->commands) {
123 retval = register_commands(CMD_CTX, NULL, pld_driver->commands);
124 if (retval != ERROR_OK) {
125 LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[1]);
126 free(pld_device->name);
127 free(pld_device);
128 return ERROR_FAIL;
129 }
130 }
131
132 if (pld_devices) {
133 /* find last pld device */
134 struct pld_device *p = pld_devices;
135 for (; p && p->next; p = p->next)
136 ;
137 if (p)
138 p->next = pld_device;
139 } else {
140 pld_devices = pld_device;
141 }
142
143 return ERROR_OK;
144 }
145
146 COMMAND_HANDLER(handle_pld_devices_command)
147 {
148 struct pld_device *p;
149 int i = 0;
150
151 if (!pld_devices) {
152 command_print(CMD, "no pld devices configured");
153 return ERROR_OK;
154 }
155
156 for (p = pld_devices; p; p = p->next)
157 command_print(CMD, "#%i: %s (driver: %s)", i++, p->name, p->driver->name);
158
159 return ERROR_OK;
160 }
161
162 COMMAND_HANDLER(handle_pld_load_command)
163 {
164 int retval;
165 struct timeval start, end, duration;
166 struct pld_device *p;
167
168 gettimeofday(&start, NULL);
169
170 if (CMD_ARGC < 2)
171 return ERROR_COMMAND_SYNTAX_ERROR;
172
173 p = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
174 if (!p) {
175 command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
176 return ERROR_OK;
177 }
178
179 struct stat input_stat;
180 if (stat(CMD_ARGV[1], &input_stat) == -1) {
181 LOG_ERROR("couldn't stat() %s: %s", CMD_ARGV[1], strerror(errno));
182 return ERROR_PLD_FILE_LOAD_FAILED;
183 }
184
185 if (S_ISDIR(input_stat.st_mode)) {
186 LOG_ERROR("%s is a directory", CMD_ARGV[1]);
187 return ERROR_PLD_FILE_LOAD_FAILED;
188 }
189
190 if (input_stat.st_size == 0) {
191 LOG_ERROR("Empty file %s", CMD_ARGV[1]);
192 return ERROR_PLD_FILE_LOAD_FAILED;
193 }
194
195 retval = p->driver->load(p, CMD_ARGV[1]);
196 if (retval != ERROR_OK) {
197 command_print(CMD, "failed loading file %s to pld device %s",
198 CMD_ARGV[1], CMD_ARGV[0]);
199 return retval;
200 } else {
201 gettimeofday(&end, NULL);
202 timeval_subtract(&duration, &end, &start);
203
204 command_print(CMD, "loaded file %s to pld device %s in %jis %jius",
205 CMD_ARGV[1], CMD_ARGV[0],
206 (intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
207 }
208
209 return ERROR_OK;
210 }
211
212 static const struct command_registration pld_exec_command_handlers[] = {
213 {
214 .name = "devices",
215 .handler = handle_pld_devices_command,
216 .mode = COMMAND_EXEC,
217 .help = "list configured pld devices",
218 .usage = "",
219 },
220 {
221 .name = "load",
222 .handler = handle_pld_load_command,
223 .mode = COMMAND_EXEC,
224 .help = "load configuration file into PLD",
225 .usage = "pld_name filename",
226 },
227 COMMAND_REGISTRATION_DONE
228 };
229
230 static int pld_init(struct command_context *cmd_ctx)
231 {
232 if (!pld_devices)
233 return ERROR_OK;
234
235 return register_commands(cmd_ctx, "pld", pld_exec_command_handlers);
236 }
237
238 COMMAND_HANDLER(handle_pld_init_command)
239 {
240 if (CMD_ARGC != 0)
241 return ERROR_COMMAND_SYNTAX_ERROR;
242
243 static bool pld_initialized;
244 if (pld_initialized) {
245 LOG_INFO("'pld init' has already been called");
246 return ERROR_OK;
247 }
248 pld_initialized = true;
249
250 LOG_DEBUG("Initializing PLDs...");
251 return pld_init(CMD_CTX);
252 }
253
254 static const struct command_registration pld_config_command_handlers[] = {
255 {
256 .name = "create",
257 .mode = COMMAND_CONFIG,
258 .handler = handle_pld_create_command,
259 .help = "create a PLD device",
260 .usage = "name.pld driver_name [driver_args ... ]",
261 },
262 {
263 .name = "init",
264 .mode = COMMAND_CONFIG,
265 .handler = handle_pld_init_command,
266 .help = "initialize PLD devices",
267 .usage = ""
268 },
269 COMMAND_REGISTRATION_DONE
270 };
271 static const struct command_registration pld_command_handler[] = {
272 {
273 .name = "pld",
274 .mode = COMMAND_ANY,
275 .help = "programmable logic device commands",
276 .usage = "",
277 .chain = pld_config_command_handlers,
278 },
279 COMMAND_REGISTRATION_DONE
280 };
281 int pld_register_commands(struct command_context *cmd_ctx)
282 {
283 return register_commands(cmd_ctx, NULL, pld_command_handler);
284 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)