Mercurial > flash_v2
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 |
