comparison packages/devs/flash/synthv2/current/src/synth.c @ 1702:0673c75f3a08

Import the first version of the synth flash driver which uses the V2 API.
author asl
date Thu, 05 Aug 2004 13:25:32 +0000
parents
children a24dbf2587a3
comparison
equal deleted inserted replaced
1701:773d77981a7d 1702:0673c75f3a08
1 //==========================================================================
2 //
3 // synth.c
4 //
5 // Flash programming
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s): andrew.lunn@ascom.ch
44 // Contributors: jlarmour
45 // Date: 2001-10-30
46 // Purpose:
47 // Description:
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/devs_flash_synth_v2.h>
54
55 #include <cyg/hal/hal_io.h>
56 #include <cyg/infra/cyg_ass.h>
57 #include <string.h>
58
59 #define _FLASH_PRIVATE_
60 #include <cyg/io/flash.h>
61 #include <cyg/flash/synth.h>
62
63 /* Helper function. The Linux system call cannot pass 6 parameters. Instead
64 a structure is filled in and passed as one parameter */
65 static int
66 cyg_hal_sys_do_mmap(void *addr, unsigned long length, unsigned long prot,
67 unsigned long flags, unsigned long fd, unsigned long off)
68 {
69
70 struct cyg_hal_sys_mmap_args args;
71
72 args.addr = (unsigned long) addr;
73 args.len = length;
74 args.prot = prot = prot;
75 args.flags = flags;
76 args.fd = fd;
77 args.offset = off;
78
79 return (cyg_hal_sys_mmap(&args));
80 }
81
82 static int
83 synth_flash_init(struct cyg_flash_dev *dev)
84 {
85 struct cyg_flash_synth_config *config = dev->config;
86 struct cyg_flash_synth_priv *priv = dev->priv;
87 cyg_flashaddr_t base;
88 int flags=CYG_HAL_SYS_MAP_SHARED;
89
90 priv->flashfd =
91 cyg_hal_sys_open(config->filename,
92 CYG_HAL_SYS_O_RDWR,
93 CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|
94 CYG_HAL_SYS_S_IRWXO);
95 if (priv->flashfd == -ENOENT) {
96 long w, bytesleft;
97 char buf[128];
98
99 priv->flashfd = cyg_hal_sys_open(
100 config->filename,
101 CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT,
102 CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
103 CYG_ASSERT( priv->flashfd >= 0,
104 "Opening of the file for the synth flash failed!");
105 // fill with 0xff
106 memset( buf, 0xff, sizeof(buf) );
107 bytesleft = config->block_size * config->blocks +
108 config->boot_block_size * config->boot_blocks;
109
110 while (bytesleft > 0) {
111 int bytesneeded;
112 bytesneeded = bytesleft < sizeof(buf) ?
113 bytesleft : sizeof(buf);
114
115 w = cyg_hal_sys_write( priv->flashfd, buf,
116 bytesneeded );
117 CYG_ASSERT(w == bytesneeded,
118 "initialization of flash file failed");
119 bytesleft -= bytesneeded;
120 } // while
121 }
122 CYG_ASSERT( priv->flashfd >= 0,
123 "Opening of the file for the synth flash failed!");
124 if ( priv->flashfd <= 0 ) {
125 return CYG_FLASH_ERR_HWR;
126 }
127
128 if (dev->start != 0) {
129 flags |= CYG_HAL_SYS_MAP_FIXED;
130 }
131 base = (cyg_flashaddr_t)cyg_hal_sys_do_mmap(
132 (void *)dev->start,
133 config->blocks * config->block_size +
134 config->boot_block_size * config->boot_blocks,
135 CYG_HAL_SYS_PROT_READ,
136 flags,
137 priv->flashfd,
138 0l);
139 CYG_ASSERT( (int) base > 0, "mmap of flash file failed!" );
140 if (base <= 0) {
141 return CYG_FLASH_ERR_HWR;
142 }
143 dev->start = base;
144 dev->end = base + (config->blocks * config->block_size) +
145 (config->boot_blocks * config->boot_block_size) - 1;
146 if (config->boot_blocks) {
147 if (config->boot_block_bottom) {
148 priv->block_info[0].block_size = config->boot_block_size;
149 priv->block_info[0].blocks = config->boot_blocks;
150 priv->block_info[1].block_size = config->block_size;
151 priv->block_info[1].blocks = config->blocks;
152 } else {
153 priv->block_info[0].block_size = config->block_size;
154 priv->block_info[0].blocks = config->blocks;
155 priv->block_info[1].block_size = config->boot_block_size;
156 priv->block_info[1].blocks = config->boot_blocks;
157 }
158 dev->num_block_infos = 2;
159 } else {
160 priv->block_info[0].block_size = config->block_size;
161 priv->block_info[0].blocks = config->blocks;
162 dev->num_block_infos = 1;
163 }
164 dev->block_info = &priv->block_info[0];
165
166 return CYG_FLASH_ERR_OK;
167 }
168
169 // Map a hardware status to a package error
170 static int
171 synth_flash_hwr_map_error(struct cyg_flash_dev *dev, int err)
172 {
173 return err;
174 }
175
176 /* This helps speed up the erase. */
177 static char empty[4096];
178 static cyg_bool empty_inited = false;
179
180 // Return the size of the block which is at the given address.
181 // __inline__ so that we know it will be in RAM, not ROM.
182 static __inline__ size_t
183 flash_block_size(struct cyg_flash_dev *dev, const cyg_flashaddr_t addr)
184 {
185 int i;
186 size_t offset;
187
188
189 CYG_ASSERT((addr >= dev->start) && (addr <= dev->end), "Not inside device");
190
191 offset = addr - dev->start;
192 for (i=0; i < dev->num_block_infos; i++) {
193 if (offset < (dev->block_info[i].blocks * dev->block_info[i].block_size))
194 return dev->block_info[i].block_size;
195 offset = offset -
196 (dev->block_info[i].blocks * dev->block_info[i].block_size);
197 }
198 CYG_FAIL("Programming error");
199 return 0;
200 }
201
202 static int
203 synth_flash_erase_block(struct cyg_flash_dev *dev,
204 const cyg_flashaddr_t block_base)
205 {
206 #ifdef CYGDBG_USE_ASSERTS
207 struct cyg_flash_synth_config *config = dev->config;
208 #endif
209 struct cyg_flash_synth_priv *priv = dev->priv;
210 int offset = (int)block_base;
211 size_t block_size;
212 int i;
213
214 offset -= dev->start;
215
216 cyg_hal_sys_lseek(priv->flashfd, offset,
217 CYG_HAL_SYS_SEEK_SET);
218
219 if (!empty_inited) {
220 memset(empty, 0xff, sizeof(empty));
221 empty_inited = true;
222 }
223
224 CYG_ASSERT(sizeof(empty) < config->block_size,
225 "Eckk! Can't work with such small blocks");
226 CYG_ASSERT((config->block_size % sizeof(empty)) == 0,
227 "Eckk! Can't work with that odd size block");
228 CYG_ASSERT(config->boot_blocks && sizeof(empty) < config->boot_block_size,
229 "Eckk! Can't work with such small blocks");
230 CYG_ASSERT((config->boot_blocks && config->block_size % sizeof(empty)) == 0,
231 "Eckk! Can't work with that odd size block");
232
233 block_size = flash_block_size(dev, block_base);
234
235 for (i=0; (i * sizeof(empty)) < block_size; i++) {
236 cyg_hal_sys_write(priv->flashfd, empty, sizeof(empty));
237 }
238 return CYG_FLASH_ERR_OK;
239 }
240
241 static int
242 synth_flash_program (struct cyg_flash_dev *dev,
243 cyg_flashaddr_t base,
244 const void* data, const size_t len)
245 {
246 struct cyg_flash_synth_priv *priv = dev->priv;
247 int offset = base;
248 offset -= dev->start;
249
250 cyg_hal_sys_lseek(priv->flashfd, offset, CYG_HAL_SYS_SEEK_SET);
251 cyg_hal_sys_write(priv->flashfd, data, len);
252
253 return CYG_FLASH_ERR_OK;
254 }
255
256 #define QUERY "Linux Synthetic Flash"
257
258 static size_t
259 synth_flash_query(struct cyg_flash_dev *dev, void * data,
260 const size_t len)
261 {
262 memcpy(data,QUERY,sizeof(QUERY));
263 return sizeof(QUERY);
264 }
265
266 static struct cyg_flash_synth_config config = {
267 CYGNUM_FLASH_SYNTH_V2_BLOCKSIZE,
268 CYGNUM_FLASH_SYNTH_V2_NUMBLOCKS,
269 CYGNUM_FLASH_SYNTH_V2_BOOT_BLOCKSIZE,
270 CYGNUM_FLASH_SYNTH_V2_NUMBOOT_BLOCKS,
271 CYGNUM_FLASH_SYNTH_V2_BOOT_BLOCK_BOTTOM,
272 CYGDAT_FLASH_SYNTH_V2_FILENAME
273 };
274
275 CYG_FLASH_FUNS(cyg_flash_synth_funs,
276 synth_flash_init,
277 synth_flash_query,
278 synth_flash_erase_block,
279 synth_flash_program,
280 NULL, // read
281 synth_flash_hwr_map_error,
282 NULL, // lock
283 NULL); // unlock
284
285 CYG_FLASH_DRIVER(cyg_flash_synth_flashdev,
286 &cyg_flash_synth_funs,
287 &config,
288 CYGMEM_FLASH_SYNTH_V2_BASE,
289 sizeof(struct cyg_flash_synth_priv));
290
291 // EOF synth.c