d021f7bfc6089d4a7739700cd537d5840d5ae851
[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, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "pld.h"
25 #include "log.h"
26 #include "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 {
35         &virtex2_pld,
36         NULL,
37 };
38
39 static struct pld_device *pld_devices;
40 static struct command *pld_cmd;
41
42 struct pld_device *get_pld_device_by_num(int num)
43 {
44         struct pld_device *p;
45         int i = 0;
46
47         for (p = pld_devices; p; p = p->next)
48         {
49                 if (i++ == num)
50                 {
51                         return p;
52                 }
53         }
54
55         return NULL;
56 }
57
58 /* pld device <driver> [driver_options ...]
59  */
60 COMMAND_HANDLER(handle_pld_device_command)
61 {
62         int i;
63         int found = 0;
64
65         if (CMD_ARGC < 1)
66         {
67                 LOG_WARNING("incomplete 'pld device' command");
68                 return ERROR_OK;
69         }
70
71         for (i = 0; pld_drivers[i]; i++)
72         {
73                 if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0)
74                 {
75                         struct pld_device *p, *c;
76
77                         /* register pld specific commands */
78                         if (pld_drivers[i]->register_commands(CMD_CTX) != ERROR_OK)
79                         {
80                                 LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
81                                 exit(-1);
82                         }
83
84                         c = malloc(sizeof(struct pld_device));
85                         c->driver = pld_drivers[i];
86                         c->next = NULL;
87
88                         int retval = CALL_COMMAND_HANDLER(pld_drivers[i]->pld_device_command, c);
89                         if (ERROR_OK != retval)
90                         {
91                                 LOG_ERROR("'%s' driver rejected pld device", CMD_ARGV[0]);
92                                 free(c);
93                                 return ERROR_OK;
94                         }
95
96                         /* put pld device in linked list */
97                         if (pld_devices)
98                         {
99                                 /* find last pld device */
100                                 for (p = pld_devices; p && p->next; p = p->next);
101                                 if (p)
102                                         p->next = c;
103                         }
104                         else
105                         {
106                                 pld_devices = c;
107                         }
108
109                         found = 1;
110                 }
111         }
112
113         /* no matching pld driver found */
114         if (!found)
115         {
116                 LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
117                 exit(-1);
118         }
119
120         return ERROR_OK;
121 }
122
123 COMMAND_HANDLER(handle_pld_devices_command)
124 {
125         struct pld_device *p;
126         int i = 0;
127
128         if (!pld_devices)
129         {
130                 command_print(CMD_CTX, "no pld devices configured");
131                 return ERROR_OK;
132         }
133
134         for (p = pld_devices; p; p = p->next)
135         {
136                 command_print(CMD_CTX, "#%i: %s", i++, p->driver->name);
137         }
138
139         return ERROR_OK;
140 }
141
142 COMMAND_HANDLER(handle_pld_load_command)
143 {
144         int retval;
145         struct timeval start, end, duration;
146         struct pld_device *p;
147
148         gettimeofday(&start, NULL);
149
150         if (CMD_ARGC < 2)
151         {
152                 command_print(CMD_CTX, "usage: pld load <device#> <file>");
153                 return ERROR_OK;
154         }
155
156         unsigned dev_id;
157         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
158         p = get_pld_device_by_num(dev_id);
159         if (!p)
160         {
161                 command_print(CMD_CTX, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
162                 return ERROR_OK;
163         }
164
165         if ((retval = p->driver->load(p, CMD_ARGV[1])) != ERROR_OK)
166         {
167                 command_print(CMD_CTX, "failed loading file %s to pld device %u",
168                         CMD_ARGV[1], dev_id);
169                 switch (retval)
170                 {
171                 }
172                 return retval;
173         }
174         else
175         {
176                 gettimeofday(&end, NULL);
177                 timeval_subtract(&duration, &end, &start);
178
179                 command_print(CMD_CTX, "loaded file %s to pld device %u in %jis %jius",
180                         CMD_ARGV[1], dev_id,
181                         (intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
182         }
183
184         return ERROR_OK;
185 }
186
187 int pld_init(struct command_context *cmd_ctx)
188 {
189         if (!pld_devices)
190                 return ERROR_OK;
191
192         register_command(cmd_ctx, pld_cmd, "devices",
193                         handle_pld_devices_command, COMMAND_EXEC,
194                         "list configured pld devices");
195         register_command(cmd_ctx, pld_cmd, "load",
196                         handle_pld_load_command, COMMAND_EXEC,
197                         "load configuration <file> into programmable logic device");
198
199         return ERROR_OK;
200 }
201
202 int pld_register_commands(struct command_context *cmd_ctx)
203 {
204         pld_cmd = register_command(cmd_ctx, NULL, "pld", NULL, COMMAND_ANY, "programmable logic device commands");
205
206         register_command(cmd_ctx, pld_cmd, "device", handle_pld_device_command, COMMAND_CONFIG, NULL);
207
208         return ERROR_OK;
209 }