Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /* Trivial Flash Programmer                                  */
0002 
0003 /* Author: Till Straumann <strauman@slac.stanford.edu>, 2006 */
0004 
0005 /* To keep things simple, this driver makes a few assumptions about the
0006  * hardware:
0007  *
0008  * - no CFI
0009  * - devices operate with 16-bit data width
0010  * - two devices are used in parallel (stride 4) to
0011  *   provide 32-bit data. I.e., the devices are
0012  *   organized like this:
0013  *   unsigned short flash[FLASH_SIZE][2];
0014  * - no endianness issues (i.e., flash endianness ==  CPU endianness)
0015  * - fixed block size
0016  * - fixed buffer size
0017  * - all devices in a bank are identical
0018  * - NOT THREAD SAFE; no locking scheme is implemented.
0019  * - cannot copy within same flash bank.
0020  * - timeout uses polling/busy-wait.
0021  *
0022  * NOTE: some attempts have been made to remove the restrictions
0023  * on stride and 16-bit width with the goal to support widths 1/2 (bytes)
0024  * and strides 1/2/4 and all (legal) combinations thereof.
0025  * However, the intel chip driver only implements stride 4 / width 2
0026  * and other combinations are untested.
0027  */
0028 
0029 /*
0030  * Authorship
0031  * ----------
0032  * This software was created by
0033  *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
0034  *     Stanford Linear Accelerator Center, Stanford University.
0035  *
0036  * Acknowledgement of sponsorship
0037  * ------------------------------
0038  * The software was produced by
0039  *     the Stanford Linear Accelerator Center, Stanford University,
0040  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0041  *
0042  * Government disclaimer of liability
0043  * ----------------------------------
0044  * Neither the United States nor the United States Department of Energy,
0045  * nor any of their employees, makes any warranty, express or implied, or
0046  * assumes any legal liability or responsibility for the accuracy,
0047  * completeness, or usefulness of any data, apparatus, product, or process
0048  * disclosed, or represents that its use would not infringe privately owned
0049  * rights.
0050  *
0051  * Stanford disclaimer of liability
0052  * --------------------------------
0053  * Stanford University makes no representations or warranties, express or
0054  * implied, nor assumes any liability for the use of this software.
0055  *
0056  * Stanford disclaimer of copyright
0057  * --------------------------------
0058  * Stanford University, owner of the copyright, hereby disclaims its
0059  * copyright and all other rights in this software.  Hence, anyone may
0060  * freely use it for any purpose without restriction.
0061  *
0062  * Maintenance of notices
0063  * ----------------------
0064  * In the interest of clarity regarding the origin and status of this
0065  * SLAC software, this and all the preceding Stanford University notices
0066  * are to remain affixed to any copy or derivative of this software made
0067  * or distributed by the recipient and are to be affixed to any copy of
0068  * software made or distributed by the recipient that contains a copy or
0069  * derivative of this software.
0070  *
0071  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0072  */
0073 #ifndef TESTING
0074 #include <rtems.h>
0075 #include <bsp/flashPgm.h>
0076 #include <bsp/flashPgmPvt.h>
0077 #else
0078 #include "flashPgm.h"
0079 #include "flashPgmPvt.h"
0080 #endif
0081 
0082 #include <unistd.h>
0083 #include <stdio.h>
0084 #include <inttypes.h>
0085 #include <ctype.h>
0086 #include <fcntl.h>
0087 #include <stdlib.h>
0088 
0089 #define  DEBUG      0
0090 #undef   DEBUG
0091 
0092 #ifdef   DEBUG
0093 #define  STATIC
0094 #else
0095 #define  STATIC             static
0096 #endif
0097 
0098 /* Forward decls. */
0099 
0100 STATIC uint32_t
0101 BSP_flashProbeSize(struct bankdesc *b);
0102 
0103 STATIC struct bankdesc *
0104 bankValidate(int bank, int quiet);
0105 
0106 static struct bankdesc *
0107 argcheck(int bank, uint32_t offset, const char *src, uint32_t size);
0108 
0109 /* Type definitions */
0110 
0111 union bconv {
0112     uint32_t u;
0113     uint16_t s[2];
0114     char     c[4];
0115 };
0116 
0117 /* Little helpers... */
0118 
0119 /* Read parallel devices */
0120 static void
0121 rd_par(struct bankdesc *b, union bconv *pv, uint32_t a)
0122 {
0123     if ( 4 == FLASH_STRIDE(b) ) {
0124         pv->u    = *(_u32_a_t*)a;
0125     } else if ( 2 == FLASH_STRIDE(b) ) {
0126         pv->s[0] = *(_u16_a_t*)a;
0127     } else {
0128         pv->c[0] = *(_u8_a_t*)a;
0129     }
0130 }
0131 
0132 /* 'flush' input buffer and get an upper-case char from stdin */
0133 STATIC int
0134 getUc(void)
0135 {
0136     fseek(stdin, 0, SEEK_END);
0137     return toupper(getchar());
0138 }
0139 
0140 /* Advance rotating progress indicator on stdout.
0141  * The idea is that the caller updates a state variable
0142  * using 'flip':
0143  *
0144  * unsigned f = 0;
0145  *
0146  *    // advance indicator
0147  *    f = flip(f);
0148  *
0149  *    ...
0150  *
0151  *    // erase indicator
0152  *    wipe(f);
0153  */
0154 static unsigned flip(unsigned x)
0155 {
0156 static char bar[]= { '/', '-', '\\', '|' };
0157     putchar('\b');
0158     putchar(bar[ x & 3]);
0159     fflush(stdout);
0160     return x+1;
0161 }
0162 
0163 /* If f!=0 then erase one char on stdout.
0164  * ( If 'flip' was never called then f should still
0165  * be zero and no action is taken).
0166  */
0167 static void wipe(unsigned f)
0168 {
0169     if ( f ) {
0170         putchar('\b');
0171         putchar(' ');
0172         putchar('\b');
0173         fflush(stdout);
0174     }
0175 }
0176 
0177 /* lookup vendor ID in table of known vendors using ops
0178  * associated with the vendor.
0179  */
0180 STATIC struct vendesc *
0181 knownVendor(struct bankdesc *b, uint32_t addr, uint32_t *pd, unsigned quiet)
0182 {
0183 uint32_t        v;
0184 struct vendesc *rval;
0185 
0186     for ( rval=b->knownVendors; rval->name; rval++ ) {
0187 
0188         if ( rval->ops->get_id(b, addr, &v, pd) ) {
0189             if ( quiet < 2 )
0190                 fprintf(stderr,"Unable to read vendor/device info at 0x%08"PRIx32"\n", addr);
0191             return 0;
0192         }
0193 
0194         if ( rval->id == v ) {
0195             return rval;
0196         }
0197     }
0198     if ( quiet < 2 )
0199         fprintf(stderr,"Unknown vendor id (0x%04"PRIx32") at 0x%08"PRIx32"\n",v, addr);
0200     return 0;
0201 }
0202 
0203 /* lookup device ID in table of known devices */
0204 STATIC struct devdesc *
0205 knownDevice(struct vendesc *v, uint32_t d)
0206 {
0207 struct devdesc *rval;
0208     for ( rval=v->known_devs; rval->name; rval++ ) {
0209         if ( rval->id == d ) {
0210             return rval;
0211         }
0212     }
0213     return 0;
0214 }
0215 
0216 /* Write 'n_words' (32-bit) from 'src' to 'addr'ess on flash.
0217  * (src is a char* to emphasize that no src-alignment is required)
0218  *
0219  * RETURNS: 0 on success, (destination) address of failure on error.
0220  *
0221  *   NOTES: - device switched back to array mode on exit.
0222  *          - 'addr' must be 32-bit aligned.
0223  */
0224 
0225 STATIC uint32_t
0226 BSP_flashWriteDataRaw(struct bankdesc *b, uint32_t addr, const char *src, uint32_t n_words, int quiet)
0227 {
0228 uint32_t   sta;
0229 uint32_t   N;
0230 uint32_t   nxt, a, i, bufsz;
0231 uint32_t   then, now;
0232 unsigned   f;
0233 const char *s;
0234 
0235 #ifdef DEBUG
0236     printf("\nflashWriteDataRaw(0x%08"PRIx32", %p, 0x%"PRIx32")\n", addr, src, n_words);
0237 #endif
0238 
0239     if ( 0 == n_words ) {
0240         return 0;
0241     }
0242 
0243     if ( !b ) {
0244         fprintf(stderr,"Missing bank descriptor argument\n");
0245         return -1;
0246     }
0247     if ( !b->dd ) {
0248         fprintf(stderr,"Bank descriptor not initialized\n");
0249         return -1;
0250     }
0251 
0252     if ( addr & (FLASH_STRIDE(b)-1) ) {
0253         fprintf(stderr,"Misaligned address (not on word boundary) 0x%08"PRIx32"\n", addr);
0254         return -1;
0255     }
0256 
0257     if ( (sta = b->ops->check_ready(b, addr)) ) {
0258         /* Error msgs have already been printed */
0259         return addr;
0260     }
0261 
0262     bufsz = FLASH_NDEVS(b) * b->dd->bufsz;
0263 
0264     then = BSP_flashBspOps.read_us_timer();
0265 
0266     for ( f = 0, a = addr, s=src, i = n_words; i ; s+=N ) {
0267         /* start of next buffer */
0268         nxt = (a + bufsz) & ~(bufsz-1);
0269 
0270         /* number of bytes */
0271         N = (nxt - a);
0272 
0273         if ( N > i * FLASH_STRIDE(b) )
0274             N = i * FLASH_STRIDE(b);
0275 
0276         i -= N/FLASH_STRIDE(b);
0277 
0278         if ( (sta = b->ops->write_line(b, a, s, N)) )
0279             goto bail;
0280 
0281         if ( ! quiet && (now = BSP_flashBspOps.read_us_timer()) - then > 500000 ) {
0282             f = flip(f);
0283             then = now;
0284         }
0285 
0286         a = nxt;
0287     }
0288 
0289     sta = 0;
0290 
0291     /* verify */
0292     for ( i=0, a=addr; i < n_words * FLASH_STRIDE(b); i++, a++ ) {
0293         if ( *(char*)a != src[i] ) {
0294             sta = -2;
0295             goto bail;
0296         }
0297     }
0298 
0299 bail:
0300     if ( ! quiet ) {
0301         wipe(f);
0302     }
0303     if ( sta ) {
0304         switch ( sta ) {
0305             default:
0306                 fprintf(stderr,"Error (flashWriteDataRaw): write error\n");
0307                 b->ops->print_stat(b, sta,0);
0308             break;
0309 
0310             case -1:
0311                 fprintf(stderr,"Error (flashWriteDataRaw): Timeout\n");
0312             break;
0313 
0314             case -2:
0315                 fprintf(stderr,"Error (flashWriteDataRaw): write verification failed at 0x%08"PRIx32"\n", a);
0316             break;
0317         }
0318         b->ops->array_mode(b, a);
0319     } else {
0320         /* no errors */
0321         a = 0;
0322     }
0323     return a;
0324 }
0325 
0326 
0327 /* Query device for basic information verifying that we talk
0328  * to a 'known'/'supported' device.
0329  *
0330  * This is not really clean since (until we implement CFI)
0331  * we already need to know what kind of device it is to
0332  * be able to read its ID...
0333  *
0334  *   NOTES: - device switched back to array mode on exit.
0335  *          - 'addr' must be 32-bit aligned.
0336  */
0337 
0338 STATIC struct devdesc *
0339 BSP_flashCheckId(struct bankdesc *b, uint32_t addr, unsigned quiet)
0340 {
0341 uint8_t  x;
0342 uint32_t d;
0343 struct vendesc  *vd;
0344 struct devdesc  *dd;
0345 
0346     /* check if it's flash at all: */
0347     x = *(A8)addr;
0348     *(A8)addr = ~x;
0349     if ( x != *(A8)addr ) {
0350         /* restore */
0351         *(A8)addr = x;
0352         if ( quiet < 3 )
0353             fprintf(stderr,"Addr 0x%08"PRIx32" seems to be RAM!\n", addr);
0354         return 0;
0355     }
0356 
0357     if ( !(vd = knownVendor(b, addr, &d, quiet)) ) {
0358         return 0;
0359     }
0360 
0361     /* Use the vendor ops for this bank */
0362     b->ops    = vd->ops;
0363 
0364     if ( !quiet )
0365         printf("Flash device, vendor: %s", vd->name);
0366 
0367     if ( !(dd = knownDevice(vd, d)) ) {
0368         if ( !quiet )
0369             printf("\n");
0370         if ( quiet < 2 )
0371             fprintf(stderr,"Unknown device id (0x%04"PRIx32") at 0x%08"PRIx32"\n",d, addr);
0372         return 0;
0373     }
0374 
0375     /* logical sector size is device sector size
0376      * multiplied by # of devices in parallel
0377      */
0378     b->fblksz = dd->fblksz * FLASH_NDEVS(b);
0379 
0380     if ( !quiet )
0381         printf(", device: %s -- size 0x%08"PRIx32" bytes\n", dd->name, dd->size);
0382     return dd;
0383 }
0384 
0385 /* We don't have device info yet so just
0386  * use 64k alignment
0387  */
0388 #define SCAN_BACK_OFFSET    0x10000
0389 
0390 /* Scan address range for flash devices and compute total size
0391  * of bank.
0392  *
0393  * RETURNS: size in bytes.
0394  */
0395 STATIC uint32_t
0396 BSP_flashProbeSize(struct bankdesc *b)
0397 {
0398 int             max = b->max_size;
0399 uint32_t        rval;
0400 struct devdesc  *dd;
0401 unsigned        q;
0402     if ( max > 0 ) {
0403         for ( rval = 0, q=1; rval < max && (dd = BSP_flashCheckId(b, b->start + rval, q)); q=3 ) {
0404             rval += dd->size * FLASH_NDEVS(b);
0405         }
0406     } else {
0407         /* bank is populated from the top; scan backwards */
0408         max = -max;
0409         for ( rval = 0, q=1; rval < max && (dd = BSP_flashCheckId(b, b->start + max - SCAN_BACK_OFFSET - rval, q)); q=3 ) {
0410             rval += dd->size * FLASH_NDEVS(b);
0411         }
0412         b->start += max - rval;
0413     }
0414     return rval;
0415 }
0416 
0417 uint32_t
0418 BSP_flashStart(int bank)
0419 {
0420 struct bankdesc *b;
0421     if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
0422         return -1;
0423     return b->start;
0424 }
0425 
0426 uint32_t
0427 BSP_flashSize(int bank)
0428 {
0429 struct bankdesc *b;
0430     if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
0431         return -1;
0432     return b->size;
0433 }
0434 
0435 uint32_t
0436 BSP_flashBlockSize(int bank)
0437 {
0438 struct bankdesc *b;
0439     if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
0440         return -1;
0441     return b->fblksz;
0442 }
0443 
0444 
0445 #ifndef TESTING
0446 
0447 /* Obtain bank description making sure it is initialized and not write protected */
0448 STATIC struct bankdesc *
0449 bankValidate(int bank, int quiet)
0450 {
0451 struct bankdesc *b = BSP_flashBspOps.bankcheck(bank, quiet);
0452 
0453     /* If flash is write-protected then we can't even talk to it... */
0454     if ( BSP_flashBspOps.flash_wp(bank, -1) ) {
0455         fprintf(stderr,"Flash bank #%i is write-protected; use 'BSP_flashWriteEnable(int bank)' and/or jumper\n", bank);
0456         return 0;
0457     }
0458 
0459     if ( !b->size && !(b->size = BSP_flashProbeSize(b)) ) {
0460         fprintf(stderr,"Configuration Error - unable to determine flash size\n");
0461         return 0;
0462     }
0463 
0464     if ( !b->dd && !(b->dd = BSP_flashCheckId(b, b->start,1)) ) {
0465         fprintf(stderr,"Error: unable to detect flash device in bank #%i\n", bank);
0466         return 0;
0467     }
0468     return b;
0469 }
0470 
0471 /* Validate arguments and write-protection status of 'bank'.
0472  *
0473  *    'bank': 0..max bank supported by board.
0474  *  'offset': 0..bank size - 1
0475  *     'src': src .. src + size - 1 must not overlap bank; 'src' may be NULL
0476  *            (check is skipped in this case)
0477  *
0478  *      RETURNS: pointer to bank description on success, NULL on error (invalid args;
0479  *               error message is printed to stderr).
0480  *
0481  * SIDE EFFECTS: probes for bank size and stores result in bank description table.
0482  */
0483 
0484 static struct bankdesc *
0485 argcheck(int bank, uint32_t offset, const char *src, uint32_t size)
0486 {
0487 struct bankdesc *b;
0488 
0489     if ( !(b=bankValidate(bank, 0)) ) {
0490         return 0;
0491     }
0492 
0493     if ( offset + size > b->size ) {
0494         fprintf(stderr,"Error: requested size exceeds available flash (0x%08"PRIx32" bytes)\n", b->size);
0495         return 0;
0496     }
0497 
0498     if ( src && ( src + size > (char*)b->start && src < (char*)(b->start + b->size) ) ) {
0499         fprintf(stderr,"Error: cannot copy data within flash bank\n");
0500         return 0;
0501     }
0502 
0503 
0504     return b;
0505 }
0506 
0507 /* Calculate region that needs to be erased from 'offset' and 'n_bytes'
0508  * handling alignment and checking for blank areas that need not be
0509  * erased.
0510  * Ask for user confirmation and erase calculated region.
0511  *
0512  * RETURNS: 0 on success, -1 or destination address on error.
0513  *
0514  *   NOTES: - device switched back to array mode on exit.
0515  *          - prints progress/messages.
0516  */
0517 STATIC int
0518 regionCheckAndErase(int bank, uint32_t offset, const char *src, uint32_t n_bytes, int quiet)
0519 {
0520 struct bankdesc *b;
0521 uint32_t         i;
0522 char            *p;
0523 uint32_t        a,e;
0524 
0525     if ( ! (b = argcheck(bank, offset, src, n_bytes)) )
0526         return -1;
0527 
0528     a = offset & ~(b->fblksz - 1);
0529     e = (offset + n_bytes +  b->fblksz - 1) & ~ (b->fblksz - 1);
0530 
0531     /* If 'offset' is not block-aligned then rest of the block must
0532      * be free.
0533      */
0534     if ( a != offset ) {
0535         a += b->fblksz;
0536         i  = ( a > offset + n_bytes ) ? offset + n_bytes : a;
0537         for ( p = (char*)(b->start + offset); p < (char*)(b->start + i); p++ ) {
0538             if ( (char)0xff != *p ) {
0539                 if ( ! quiet ) {
0540                     fprintf(stderr,"Starting offset not block-aligned and destination area not empty.\n");
0541                     fprintf(stderr,"I'll need to erase data below destination start\n");
0542                 }
0543                 a -= b->fblksz;
0544                 break;
0545             }
0546         }
0547     }
0548     if ( e != offset + n_bytes ) {
0549         e -= b->fblksz;
0550         i  = ( e < offset ) ? offset : e;
0551         for ( p = (char*)(b->start + i); p < (char*)(b->start + offset + n_bytes); p++ ) {
0552             if ( (char)0xff != *p ) {
0553                 if ( ! quiet ) {
0554                     fprintf(stderr,"Ending offset not block-aligned and destination area not empty.\n");
0555                     fprintf(stderr,"I'll need to erase data beyond destination end\n");
0556                 }
0557                 e += b->fblksz;
0558                 break;
0559             }
0560         }
0561     }
0562     if ( ! quiet ) {
0563         if ( e > a )
0564             printf("ERASING 0x%08"PRIx32" .. 0x%08"PRIx32"\n", (b->start+a), (b->start + e - 1));
0565         printf("WRITING 0x%08"PRIx32" .. 0x%08"PRIx32"\n", (b->start+offset), (b->start + offset + n_bytes - 1));
0566         printf("OK to proceed y/[n]?"); fflush(stdout);
0567         if ( 'Y' != getUc() ) {
0568             printf("ABORTED\n");
0569             return -1;
0570         }
0571     }
0572     if ( e > a ) {
0573         if ( quiet < 2 ) {
0574             printf("ERASING  "); fflush(stdout);
0575         }
0576 
0577         if ( (i = BSP_flashErase(bank, a, e-a, quiet ? quiet : 1)) )
0578             return i;
0579 
0580         if ( quiet < 2 ) {
0581             printf("DONE\n");
0582         }
0583     }
0584 
0585     return 0;
0586 }
0587 
0588 /* Write to a flash region ('offset'..'offset'+'n_bytes'-1 on 'bank').
0589  *
0590  * RETURNS: 0 on success, -1 or destination address on error.
0591  *
0592  *   NOTES: - device switched back to array mode on exit.
0593  *          - no erase operation is performed.
0594  *          - written data is verified against source.
0595  */
0596 
0597 STATIC int
0598 BSP_flashWriteRegion(int bank, uint32_t offset, const char *src, uint32_t n_bytes, int quiet)
0599 {
0600 struct bankdesc *b = BSP_flashBspOps.bankcheck(bank, 0);    /* caller did bankValidate() */
0601 uint32_t     ab = offset & ~(b->fblksz - 1);
0602 uint32_t     eb = (offset + n_bytes + b->fblksz - 1) & ~(b->fblksz - 1);
0603 uint32_t     o,i,a,e;
0604 int          err;
0605 const char   *p;
0606 union bconv  buf;
0607 
0608     /* unlock */
0609     for ( i=ab; i<eb; i+=b->fblksz ) {
0610         b->ops->unlock_block(b, b->start + i );
0611     }
0612 
0613     err = 0;
0614     p = src;
0615 
0616     /* handle misaligned offset merging old contents */
0617     o = b->start + offset;
0618     a = o & ~(FLASH_STRIDE(b)-1);
0619     e = (o + n_bytes) & ~(FLASH_STRIDE(b)-1);
0620 
0621     if ( o > a ) {
0622         i = o - a;
0623 
0624         rd_par(b, &buf, a);
0625 
0626         while ( i < FLASH_STRIDE(b) && p < src + n_bytes ) {
0627             buf.c[i++] = *p++;
0628         }
0629         if ( (err = BSP_flashWriteDataRaw(b, a, buf.c, 1, quiet)) )
0630             goto bail;
0631         a += FLASH_STRIDE(b);
0632     }
0633 
0634 
0635     /* caution if misaligned data covering only one or two words */
0636 
0637     if ( e > a ) {
0638         i = (e-a);
0639         if ( (err = BSP_flashWriteDataRaw(b, a, p, i/FLASH_STRIDE(b), quiet)) )
0640             goto bail;
0641         p += i;
0642     }
0643 
0644     /* handle misaligned end */
0645     if ( o + n_bytes > e)  {
0646         rd_par(b, &buf, e);
0647         for ( i=0; p < src + n_bytes; ) {
0648             buf.c[i++] = *p++;
0649         }
0650         if ( (err = BSP_flashWriteDataRaw(b, e, buf.c, 1, quiet)) )
0651             goto bail;
0652     }
0653 
0654 bail:
0655     /* lock area */
0656     for ( i=ab; i<eb; i+=b->fblksz ) {
0657         b->ops->lock_block(b, b->start + i );
0658     }
0659 
0660     /* final verification */
0661     if ( !err ) {
0662         for ( i=0; i<n_bytes; i++ ) {
0663             if ( ((char*)(b->start + offset))[i] != src[i] ) {
0664                 fprintf(stderr,"Final verification failed at offset 0x%08"PRIx32"\n", (offset + i));
0665                 return b->start + offset + i;
0666             }
0667         }
0668     }
0669 
0670     return err;
0671 }
0672 
0673 int
0674 BSP_flashErase(int bank, uint32_t offset, uint32_t size, int quiet)
0675 {
0676 struct bankdesc *b;
0677 uint32_t         a,i;
0678 int              f;
0679 
0680     if ( ! (b = argcheck(bank, offset, 0, size)) )
0681         return -1;
0682 
0683     if ( offset & (b->fblksz - 1) ) {
0684         fprintf(stderr,"Offset misaligned (needs to be multiple of 0x%08"PRIx32")\n", b->fblksz);
0685         return -1;
0686     }
0687     if ( size & (b->fblksz - 1) ) {
0688         fprintf(stderr,"Size misaligned (needs to be multiple of 0x%08"PRIx32")\n", b->fblksz);
0689         return -1;
0690     }
0691 
0692     a = b->start + offset;
0693 
0694     if ( !quiet ) {
0695         printf("ERASING Flash (Bank #%i)\n    from 0x%08"PRIx32" .. 0x%08"PRIx32"\nproceed y/[n]?",
0696             bank, a, (a+size-1));
0697         fflush(stdout);
0698         if ( 'Y' != getUc() ) {
0699             printf("ABORTED\n");
0700             return -1;
0701         }
0702     }
0703     f = 0;
0704     while ( size ) {
0705         /* work to do ? */
0706         for ( i = 0; i<b->fblksz; i++ ) {
0707             if ( (char)0xff != ((char*)a)[i] ) {
0708                 b->ops->unlock_block(b, a);
0709                 i = b->ops->erase_block(b, a);
0710                 b->ops->lock_block(b, a);
0711                 if (i) {
0712                     wipe(f);
0713                     return a;
0714                 }
0715                 break;
0716             }
0717         }
0718 
0719         if ( quiet < 2 ) {
0720             f = flip(f);
0721         }
0722 
0723         a    += b->fblksz;
0724         size -= b->fblksz;
0725     }
0726     b->ops->array_mode(b, a);
0727     if ( quiet < 2 ) {
0728         wipe(f);
0729     }
0730     return 0;
0731 }
0732 
0733 int
0734 BSP_flashWrite(int bank, uint32_t offset, const char *src, uint32_t n_bytes, int quiet)
0735 {
0736 int      rval;
0737 
0738     if ( !src ) {
0739         fprintf(stderr,"Error: Data source pointer is NULL\n");
0740         return -1;
0741     }
0742 
0743     if ( (rval = regionCheckAndErase(bank, offset, src, n_bytes, quiet)) )
0744         return rval;
0745 
0746     if ( ! quiet ) {
0747         printf("WRITING  "); fflush(stdout);
0748     }
0749 
0750     rval = BSP_flashWriteRegion(bank, offset, src, n_bytes, quiet);
0751 
0752     if ( !quiet && !rval ) {
0753         printf("DONE");
0754     }
0755     if ( !quiet )
0756         printf("\n");
0757     return rval;
0758 }
0759 
0760 static int
0761 bfill(int fd, char *buf, int size)
0762 {
0763 int got, avail;
0764     for (avail = size; (got = read(fd, buf, avail)) > 0; avail-=got ) {
0765         buf  += got;
0766     }
0767     return size - avail;
0768 }
0769 
0770 int
0771 BSP_flashWriteFile(int bank, uint32_t offset, const char *fname, int quiet)
0772 {
0773 int             fd   = -1;
0774 struct stat     sb;
0775 uint32_t        sz;
0776 int             rval = -1;
0777 char           *buf  = 0;
0778 uint32_t        got;
0779 struct bankdesc *b;
0780 unsigned        f    = 0;
0781 
0782     if ( ! (b = bankValidate(bank, 0)) )
0783         return -1;
0784 
0785     for ( sz = 0; -1 == fd ;  ) {
0786         if ( (fd = open(fname,O_RDONLY)) < 0 ) {
0787             perror("Opening file");
0788             return -1;
0789         }
0790 
0791         if ( sz )
0792             break;
0793 
0794         if ( fstat(fd, &sb) ) {
0795             fprintf(stderr,"Warning: fstat doesn't work; need to slurp file to determine size; please be patient.\n");
0796             FILE *f;
0797             close(fd); fd = -1;
0798             f = fopen(fname,"r");
0799             if ( !f ) {
0800                 perror("fdopen");
0801                 return -1;
0802             }
0803             while ( EOF != fgetc(f) )
0804                 sz++;
0805             fclose(f);
0806             /* reopen */
0807         } else {
0808             sz = sb.st_size;
0809         }
0810         if ( 0 == sz ) {
0811             fprintf(stderr,"Error: zero file size (?)\n");
0812             goto bail;
0813         }
0814     }
0815 
0816     if ( !(buf = malloc(b->fblksz)) ) {
0817         perror("buffer allocation");
0818         goto bail;
0819     }
0820 
0821     /* See if we can erase the entire region */
0822     if ( (rval = regionCheckAndErase(bank, offset, buf, sz, quiet)) )
0823         goto bail;
0824 
0825     /* Proceed copying chunks */
0826     if ( quiet < 2 ) {
0827         printf("WRITING  "); fflush(stdout);
0828     }
0829 
0830     while ( (got = bfill(fd, buf, b->fblksz)) > 0 && sz ) {
0831         if ( (rval = BSP_flashWriteRegion(bank, offset, buf, got, 1)) ) {
0832             wipe(f);
0833             goto bail;
0834         }
0835         offset += got;
0836         sz     -= got;
0837         if ( quiet < 2 ) {
0838             f = flip(f);
0839         }
0840     }
0841     if ( got < 0 ) {
0842         perror("reading file");
0843         rval = offset;
0844         goto bail;
0845     }
0846 
0847     if ( quiet < 2 ) {
0848         wipe(f);
0849         printf("DONE");
0850     }
0851 bail:
0852     if ( quiet < 2 ) {
0853         printf("\n");
0854     }
0855     if ( fd > -1 )
0856         close(fd);
0857     free(buf);
0858     return rval;
0859 }
0860 
0861 int
0862 BSP_flashWriteEnable(int bank)
0863 {
0864     return BSP_flashBspOps.flash_wp(bank,0);
0865 }
0866 
0867 int
0868 BSP_flashWriteDisable(int bank)
0869 {
0870     return BSP_flashBspOps.flash_wp(bank,1);
0871 }
0872 
0873 int
0874 BSP_flashDumpInfo(FILE *f)
0875 {
0876 struct bankdesc *b;
0877 int             bank;
0878 
0879     if ( !f )
0880         f = stdout;
0881 
0882     /* use 'bankValidate()' with 'quiet' flag to suppress error message when
0883      * we reach the end of the table.
0884      */
0885     for ( bank = 0; BSP_flashBspOps.bankcheck(bank,1); bank++ ) {
0886         if ( (b=argcheck(bank,0,0,0)) ) {
0887             fprintf(f,"Flash Bank #%i; 0x%08"PRIx32" .. 0x%08"PRIx32" (%"PRId32" bytes)\n",
0888                 bank, b->start, (b->start + b->size - 1), b->size);
0889             fprintf(f,"%i * %i-bit devices in parallel; block size 0x%"PRIx32"\n", FLASH_NDEVS(b), FLASH_WIDTH(b)*8, b->fblksz);
0890             BSP_flashCheckId(b, b->start, 0);
0891         }
0892     }
0893 
0894     return 0;
0895 }
0896 
0897 #else
0898 
0899 int
0900 main(int argc, char **argv)
0901 {
0902 uint32_t fla[1000];
0903 uint32_t qqq[1000];
0904 int i;
0905     for ( i=0; i<sizeof(qqq)/sizeof(qqq[0]); i++ )
0906         qqq[i] = 0xdada<<16 | i;
0907     BSP_flashWriteDataRaw(0, (uint32_t)fla, (char*)qqq, 32, 0);
0908 }
0909 #endif