]> git.sur5r.net Git - openocd/blob - src/flash/nor/virtual.c
fab521dd6cff296df8f4b7aa982109dacd1957be
[openocd] / src / flash / nor / virtual.c
1 /***************************************************************************
2  *   Copyright (C) 2010 by Spencer Oliver                                  *
3  *   spen@spen-soft.co.uk                                                  *
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  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "imp.h"
26
27 static struct flash_bank *virtual_get_master_bank(struct flash_bank *bank)
28 {
29         struct flash_bank *master_bank;
30
31         master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv);
32         if (master_bank == NULL)
33                 LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv);
34
35         return master_bank;
36 }
37
38 static void virtual_update_bank_info(struct flash_bank *bank)
39 {
40         struct flash_bank *master_bank = virtual_get_master_bank(bank);
41
42         if (master_bank == NULL)
43                 return;
44
45         /* update the info we do not have */
46         bank->size = master_bank->size;
47         bank->chip_width = master_bank->chip_width;
48         bank->bus_width = master_bank->bus_width;
49         bank->default_padded_value = master_bank->default_padded_value;
50         bank->num_sectors = master_bank->num_sectors;
51         bank->sectors = master_bank->sectors;
52 }
53
54 FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
55 {
56         if (CMD_ARGC < 7)
57                 return ERROR_COMMAND_SYNTAX_ERROR;
58
59         /* get the master flash bank */
60         const char *bank_name = CMD_ARGV[6];
61         struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name);
62
63         if (master_bank == NULL) {
64                 LOG_ERROR("master flash bank '%s' does not exist", bank_name);
65                 return ERROR_FLASH_OPERATION_FAILED;
66         }
67
68         /* save master bank name - use this to get settings later */
69         bank->driver_priv = strdup(bank_name);
70
71         return ERROR_OK;
72 }
73
74 static int virtual_protect(struct flash_bank *bank, int set, int first, int last)
75 {
76         struct flash_bank *master_bank = virtual_get_master_bank(bank);
77         int retval;
78
79         if (master_bank == NULL)
80                 return ERROR_FLASH_OPERATION_FAILED;
81
82         /* call master handler */
83         retval = master_bank->driver->protect(master_bank, set, first, last);
84         if (retval != ERROR_OK)
85                 return retval;
86
87         return ERROR_OK;
88 }
89
90 static int virtual_protect_check(struct flash_bank *bank)
91 {
92         struct flash_bank *master_bank = virtual_get_master_bank(bank);
93         int retval;
94
95         if (master_bank == NULL)
96                 return ERROR_FLASH_OPERATION_FAILED;
97
98         /* call master handler */
99         retval = master_bank->driver->protect_check(master_bank);
100         if (retval != ERROR_OK)
101                 return retval;
102
103         return ERROR_OK;
104 }
105
106 static int virtual_erase(struct flash_bank *bank, int first, int last)
107 {
108         struct flash_bank *master_bank = virtual_get_master_bank(bank);
109         int retval;
110
111         if (master_bank == NULL)
112                 return ERROR_FLASH_OPERATION_FAILED;
113
114         /* call master handler */
115         retval = master_bank->driver->erase(master_bank, first, last);
116         if (retval != ERROR_OK)
117                 return retval;
118
119         return ERROR_OK;
120 }
121
122 static int virtual_write(struct flash_bank *bank, uint8_t *buffer,
123                 uint32_t offset, uint32_t count)
124 {
125         struct flash_bank *master_bank = virtual_get_master_bank(bank);
126         int retval;
127
128         if (master_bank == NULL)
129                 return ERROR_FLASH_OPERATION_FAILED;
130
131         /* call master handler */
132         retval = master_bank->driver->write(master_bank, buffer, offset, count);
133         if (retval != ERROR_OK)
134                 return retval;
135
136         return ERROR_OK;
137 }
138
139 static int virtual_probe(struct flash_bank *bank)
140 {
141         struct flash_bank *master_bank = virtual_get_master_bank(bank);
142         int retval;
143
144         if (master_bank == NULL)
145                 return ERROR_FLASH_OPERATION_FAILED;
146
147         /* call master handler */
148         retval = master_bank->driver->probe(master_bank);
149         if (retval != ERROR_OK)
150                 return retval;
151
152         /* update the info we do not have */
153         virtual_update_bank_info(bank);
154
155         return ERROR_OK;
156 }
157
158 static int virtual_auto_probe(struct flash_bank *bank)
159 {
160         struct flash_bank *master_bank = virtual_get_master_bank(bank);
161         int retval;
162
163         if (master_bank == NULL)
164                 return ERROR_FLASH_OPERATION_FAILED;
165
166         /* call master handler */
167         retval = master_bank->driver->auto_probe(master_bank);
168         if (retval != ERROR_OK)
169                 return retval;
170
171         /* update the info we do not have */
172         virtual_update_bank_info(bank);
173
174         return ERROR_OK;
175 }
176
177 static int virtual_info(struct flash_bank *bank, char *buf, int buf_size)
178 {
179         struct flash_bank *master_bank = virtual_get_master_bank(bank);
180
181         if (master_bank == NULL)
182                 return ERROR_FLASH_OPERATION_FAILED;
183
184         snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
185                         bank->driver->name, master_bank->name, master_bank->base);
186
187         return ERROR_OK;
188 }
189
190 static int virtual_blank_check(struct flash_bank *bank)
191 {
192         struct flash_bank *master_bank = virtual_get_master_bank(bank);
193         int retval;
194
195         if (master_bank == NULL)
196                 return ERROR_FLASH_OPERATION_FAILED;
197
198         /* call master handler */
199         retval = master_bank->driver->erase_check(master_bank);
200         if (retval != ERROR_OK)
201                 return retval;
202
203         return ERROR_OK;
204 }
205
206 static int virtual_flash_read(struct flash_bank *bank,
207                 uint8_t *buffer, uint32_t offset, uint32_t count)
208 {
209         struct flash_bank *master_bank = virtual_get_master_bank(bank);
210         int retval;
211
212         if (master_bank == NULL)
213                 return ERROR_FLASH_OPERATION_FAILED;
214
215         /* call master handler */
216         retval = master_bank->driver->read(master_bank, buffer, offset, count);
217         if (retval != ERROR_OK)
218                 return retval;
219
220         return ERROR_OK;
221 }
222
223 struct flash_driver virtual_flash = {
224         .name = "virtual",
225         .flash_bank_command = virtual_flash_bank_command,
226         .erase = virtual_erase,
227         .protect = virtual_protect,
228         .write = virtual_write,
229         .read = virtual_flash_read,
230         .probe = virtual_probe,
231         .auto_probe = virtual_auto_probe,
232         .erase_check = virtual_blank_check,
233         .protect_check = virtual_protect_check,
234         .info = virtual_info,
235 };