pld.c 5.88 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/***************************************************************************
 *   Copyright (C) 2006 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   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 20 21 22 23
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "pld.h"
24
#include <helper/log.h>
25
#include <helper/time_support.h>
26 27 28 29


/* pld drivers
 */
30
extern struct pld_driver virtex2_pld;
31

32
static struct pld_driver *pld_drivers[] = {
33 34 35 36
	&virtex2_pld,
	NULL,
};

37
static struct pld_device *pld_devices;
38

39
struct pld_device *get_pld_device_by_num(int num)
40
{
41
	struct pld_device *p;
42 43
	int i = 0;

44
	for (p = pld_devices; p; p = p->next) {
45 46 47
		if (i++ == num)
			return p;
	}
zwelch's avatar
zwelch committed
48

49 50 51 52 53
	return NULL;
}

/* pld device <driver> [driver_options ...]
 */
54
COMMAND_HANDLER(handle_pld_device_command)
55 56 57
{
	int i;
	int found = 0;
zwelch's avatar
zwelch committed
58

59
	if (CMD_ARGC < 1)
Mathias K's avatar
Mathias K committed
60
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
61

62 63
	for (i = 0; pld_drivers[i]; i++) {
		if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) {
64
			struct pld_device *p, *c;
zwelch's avatar
zwelch committed
65

66
			/* register pld specific commands */
67 68
			int retval;
			if (pld_drivers[i]->commands) {
David Brownell's avatar
David Brownell committed
69
				retval = register_commands(CMD_CTX, NULL,
70
						pld_drivers[i]->commands);
71
				if (ERROR_OK != retval) {
72 73 74
					LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
					return ERROR_FAIL;
				}
75
			}
zwelch's avatar
zwelch committed
76

77
			c = malloc(sizeof(struct pld_device));
78 79
			c->driver = pld_drivers[i];
			c->next = NULL;
zwelch's avatar
zwelch committed
80

David Brownell's avatar
David Brownell committed
81 82
			retval = CALL_COMMAND_HANDLER(
					pld_drivers[i]->pld_device_command, c);
83
			if (ERROR_OK != retval) {
David Brownell's avatar
David Brownell committed
84
				LOG_ERROR("'%s' driver rejected pld device",
85
					CMD_ARGV[0]);
86 87 88
				free(c);
				return ERROR_OK;
			}
zwelch's avatar
zwelch committed
89

90
			/* put pld device in linked list */
91
			if (pld_devices) {
92
				/* find last pld device */
93 94
				for (p = pld_devices; p && p->next; p = p->next)
					;
95 96
				if (p)
					p->next = c;
97
			} else
98
				pld_devices = c;
zwelch's avatar
zwelch committed
99

100 101 102
			found = 1;
		}
	}
zwelch's avatar
zwelch committed
103

104
	/* no matching pld driver found */
105
	if (!found) {
106
		LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
107 108
		exit(-1);
	}
zwelch's avatar
zwelch committed
109

110 111 112
	return ERROR_OK;
}

113
COMMAND_HANDLER(handle_pld_devices_command)
114
{
115
	struct pld_device *p;
116
	int i = 0;
zwelch's avatar
zwelch committed
117

118
	if (!pld_devices) {
119
		command_print(CMD_CTX, "no pld devices configured");
120 121
		return ERROR_OK;
	}
zwelch's avatar
zwelch committed
122

123
	for (p = pld_devices; p; p = p->next)
124
		command_print(CMD_CTX, "#%i: %s", i++, p->driver->name);
zwelch's avatar
zwelch committed
125

126 127 128
	return ERROR_OK;
}

129
COMMAND_HANDLER(handle_pld_load_command)
130 131 132
{
	int retval;
	struct timeval start, end, duration;
133
	struct pld_device *p;
zwelch's avatar
zwelch committed
134

135
	gettimeofday(&start, NULL);
zwelch's avatar
zwelch committed
136

137
	if (CMD_ARGC < 2)
Mathias K's avatar
Mathias K committed
138
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
139

140
	unsigned dev_id;
141
	COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
142
	p = get_pld_device_by_num(dev_id);
143
	if (!p) {
144
		command_print(CMD_CTX, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
145 146
		return ERROR_OK;
	}
zwelch's avatar
zwelch committed
147

148 149
	retval = p->driver->load(p, CMD_ARGV[1]);
	if (retval != ERROR_OK) {
150
		command_print(CMD_CTX, "failed loading file %s to pld device %u",
151
			CMD_ARGV[1], dev_id);
152
		switch (retval) {
153
		}
154
		return retval;
155
	} else {
zwelch's avatar
zwelch committed
156
		gettimeofday(&end, NULL);
157
		timeval_subtract(&duration, &end, &start);
158

159
		command_print(CMD_CTX, "loaded file %s to pld device %u in %jis %jius",
160
			CMD_ARGV[1], dev_id,
161
			(intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
162
	}
zwelch's avatar
zwelch committed
163

164 165 166
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
167 168 169
static const struct command_registration pld_exec_command_handlers[] = {
	{
		.name = "devices",
David Brownell's avatar
David Brownell committed
170
		.handler = handle_pld_devices_command,
Zachary T Welch's avatar
Zachary T Welch committed
171 172
		.mode = COMMAND_EXEC,
		.help = "list configured pld devices",
173
		.usage = "",
Zachary T Welch's avatar
Zachary T Welch committed
174 175 176
	},
	{
		.name = "load",
David Brownell's avatar
David Brownell committed
177
		.handler = handle_pld_load_command,
Zachary T Welch's avatar
Zachary T Welch committed
178 179
		.mode = COMMAND_EXEC,
		.help = "load configuration file into PLD",
David Brownell's avatar
David Brownell committed
180
		.usage = "pld_num filename",
Zachary T Welch's avatar
Zachary T Welch committed
181 182 183
	},
	COMMAND_REGISTRATION_DONE
};
184 185

static int pld_init(struct command_context *cmd_ctx)
186 187 188 189
{
	if (!pld_devices)
		return ERROR_OK;

Zachary T Welch's avatar
Zachary T Welch committed
190 191
	struct command *parent = command_find_in_context(cmd_ctx, "pld");
	return register_commands(cmd_ctx, parent, pld_exec_command_handlers);
192 193
}

194 195 196 197 198
COMMAND_HANDLER(handle_pld_init_command)
{
	if (CMD_ARGC != 0)
		return ERROR_COMMAND_SYNTAX_ERROR;

199 200
	static bool pld_initialized;
	if (pld_initialized) {
201 202 203 204 205 206 207 208 209
		LOG_INFO("'pld init' has already been called");
		return ERROR_OK;
	}
	pld_initialized = true;

	LOG_DEBUG("Initializing PLDs...");
	return pld_init(CMD_CTX);
}

Zachary T Welch's avatar
Zachary T Welch committed
210 211 212 213
static const struct command_registration pld_config_command_handlers[] = {
	{
		.name = "device",
		.mode = COMMAND_CONFIG,
David Brownell's avatar
David Brownell committed
214
		.handler = handle_pld_device_command,
Zachary T Welch's avatar
Zachary T Welch committed
215
		.help = "configure a PLD device",
David Brownell's avatar
David Brownell committed
216
		.usage = "driver_name [driver_args ... ]",
Zachary T Welch's avatar
Zachary T Welch committed
217
	},
218 219 220
	{
		.name = "init",
		.mode = COMMAND_CONFIG,
David Brownell's avatar
David Brownell committed
221
		.handler = handle_pld_init_command,
222
		.help = "initialize PLD devices",
Spencer Oliver's avatar
Spencer Oliver committed
223
		.usage = ""
224
	},
Zachary T Welch's avatar
Zachary T Welch committed
225 226 227 228 229 230 231
	COMMAND_REGISTRATION_DONE
};
static const struct command_registration pld_command_handler[] = {
	{
		.name = "pld",
		.mode = COMMAND_ANY,
		.help = "programmable logic device commands",
Spencer Oliver's avatar
Spencer Oliver committed
232
		.usage = "",
Zachary T Welch's avatar
Zachary T Welch committed
233 234 235 236
		.chain = pld_config_command_handlers,
	},
	COMMAND_REGISTRATION_DONE
};
237
int pld_register_commands(struct command_context *cmd_ctx)
238
{
Zachary T Welch's avatar
Zachary T Welch committed
239
	return register_commands(cmd_ctx, NULL, pld_command_handler);
240
}