source: rtems/c/src/lib/libbsp/powerpc/shared/flash/flash.c @ 6771a9e7

4.104.114.95
Last change on this file since 6771a9e7 was 6771a9e7, checked in by Ralf Corsepius <ralf.corsepius@…>, on 08/20/08 at 09:00:11

Add missing prototypes.

  • Property mode set to 100644
File size: 20.5 KB
Line 
1/* $Id$         */
2
3/* Trivial Flash Programmer                                  */
4
5/* Author: Till Straumann <strauman@slac.stanford.edu>, 2006 */
6
7/* To keep things simple, this driver makes a few assumptions about the
8 * hardware:
9 *
10 * - no CFI
11 * - devices operate with 16-bit data width
12 * - two devices are used in parallel (stride 4) to
13 *   provide 32-bit data. I.e., the devices are
14 *   organized like this:
15 *   unsigned short flash[FLASH_SIZE][2];
16 * - no endianness issues (i.e., flash endianness ==  CPU endianness)
17 * - fixed block size
18 * - fixed buffer size
19 * - all devices in a bank are identical
20 * - NOT THREAD SAFE; no locking scheme is implemented.
21 * - cannot copy within same flash bank.
22 * - timeout uses polling/busy-wait.
23 *
24 * NOTE: some attempts have been made to remove the restrictions
25 * on stride and 16-bit width with the goal to support widths 1/2 (bytes)
26 * and strides 1/2/4 and all (legal) combinations thereof.
27 * However, the intel chip driver only implements stride 4 / width 2
28 * and other combinations are untested.
29 */
30
31/*
32 * Authorship
33 * ----------
34 * This software was created by
35 *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
36 *         Stanford Linear Accelerator Center, Stanford University.
37 *
38 * Acknowledgement of sponsorship
39 * ------------------------------
40 * The software was produced by
41 *     the Stanford Linear Accelerator Center, Stanford University,
42 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
43 *
44 * Government disclaimer of liability
45 * ----------------------------------
46 * Neither the United States nor the United States Department of Energy,
47 * nor any of their employees, makes any warranty, express or implied, or
48 * assumes any legal liability or responsibility for the accuracy,
49 * completeness, or usefulness of any data, apparatus, product, or process
50 * disclosed, or represents that its use would not infringe privately owned
51 * rights.
52 *
53 * Stanford disclaimer of liability
54 * --------------------------------
55 * Stanford University makes no representations or warranties, express or
56 * implied, nor assumes any liability for the use of this software.
57 *
58 * Stanford disclaimer of copyright
59 * --------------------------------
60 * Stanford University, owner of the copyright, hereby disclaims its
61 * copyright and all other rights in this software.  Hence, anyone may
62 * freely use it for any purpose without restriction. 
63 *
64 * Maintenance of notices
65 * ----------------------
66 * In the interest of clarity regarding the origin and status of this
67 * SLAC software, this and all the preceding Stanford University notices
68 * are to remain affixed to any copy or derivative of this software made
69 * or distributed by the recipient and are to be affixed to any copy of
70 * software made or distributed by the recipient that contains a copy or
71 * derivative of this software.
72 *
73 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
74 */
75#ifndef TESTING
76#include <rtems.h>
77#include <bsp/flashPgm.h>
78#include <bsp/flashPgmPvt.h>
79#else
80#include "flashPgm.h"
81#include "flashPgmPvt.h"
82#endif
83
84#include <stdio.h>
85#include <inttypes.h>
86#include <ctype.h>
87#include <fcntl.h>
88#include <stdlib.h>
89
90#define  DEBUG          0
91#undef   DEBUG
92
93#ifdef   DEBUG
94#define  STATIC
95#else
96#define  STATIC                         static
97#endif
98
99/* Forward decls. */
100
101STATIC uint32_t
102BSP_flashProbeSize(struct bankdesc *b);
103
104STATIC struct bankdesc *
105bankValidate(int bank, int quiet);
106
107static struct bankdesc *
108argcheck(int bank, uint32_t offset, char *src, uint32_t size);
109
110/* Type definitions */
111
112union bconv     {
113        uint32_t u;
114        uint16_t s[2];
115        char     c[4];
116};
117
118/* Little helpers... */
119
120/* Read parallel devices */
121static void
122rd_par(struct bankdesc *b, union bconv *pv, uint32_t a)
123{
124        if ( 4 == FLASH_STRIDE(b) ) {
125                pv->u    = *(_u32_a_t*)a;
126        } else if ( 2 == FLASH_STRIDE(b) ) {
127                pv->s[0] = *(_u16_a_t*)a;
128        } else {
129                pv->c[0] = *(_u8_a_t*)a;
130        }
131}
132
133/* 'flush' input buffer and get an upper-case char from stdin */
134STATIC int
135getUc(void)
136{
137        fseek(stdin, 0, SEEK_END);
138        return toupper(getchar());
139}
140
141/* Advance rotating progress indicator on stdout.
142 * The idea is that the caller updates a state variable
143 * using 'flip':
144 *
145 * unsigned f = 0;
146 *
147 *    // advance indicator
148 *    f = flip(f);
149 *
150 *    ...
151 *
152 *    // erase indicator
153 *    wipe(f);
154 */
155static unsigned flip(unsigned x)
156{
157static char bar[]= { '/', '-', '\\', '|' };
158        putchar('\b');
159        putchar(bar[ x & 3]);
160        fflush(stdout);
161        return x+1;
162}
163
164/* If f!=0 then erase one char on stdout.
165 * ( If 'flip' was never called then f should still
166 * be zero and no action is taken).
167 */
168static void wipe(unsigned f)
169{
170        if ( f ) {
171                putchar('\b');
172                putchar(' ');
173                putchar('\b');
174                fflush(stdout);
175        }
176}
177
178/* lookup vendor ID in table of known vendors using ops
179 * associated with the vendor.
180 */
181STATIC struct vendesc *
182knownVendor(struct bankdesc *b, uint32_t addr, uint32_t *pd, unsigned quiet)
183{
184uint32_t        v;
185struct vendesc *rval;
186
187        for ( rval=b->knownVendors; rval->name; rval++ ) {
188
189                if ( rval->ops->get_id(b, addr, &v, pd) ) {
190                        if ( quiet < 2 )
191                                fprintf(stderr,"Unable to read vendor/device info at 0x%08"PRIx32"\n", addr);
192                        return 0;
193                }
194
195                if ( rval->id == v ) {
196                        return rval;
197                }
198        }
199        if ( quiet < 2 )
200                fprintf(stderr,"Unknown vendor id (0x%04"PRIx32") at 0x%08"PRIx32"\n",v, addr);
201        return 0;
202}
203
204/* lookup device ID in table of known devices */
205STATIC struct devdesc *
206knownDevice(struct vendesc *v, uint32_t d)
207{
208struct devdesc *rval;
209        for ( rval=v->known_devs; rval->name; rval++ ) {
210                if ( rval->id == d ) {
211                        return rval;
212                }
213        }
214        return 0;
215}
216
217/* Write 'n_words' (32-bit) from 'src' to 'addr'ess on flash.
218 * (src is a char* to emphasize that no src-alignment is required)
219 *
220 * RETURNS: 0 on success, (destination) address of failure on error.
221 *
222 *   NOTES: - device switched back to array mode on exit.
223 *          - 'addr' must be 32-bit aligned.
224 */
225
226STATIC uint32_t
227BSP_flashWriteDataRaw(struct bankdesc *b, uint32_t addr, char *src, uint32_t n_words, int quiet)
228{
229uint32_t sta;
230uint32_t N;
231uint32_t nxt, a, i, bufsz;
232uint32_t then, now;
233unsigned f;
234char     *s;
235
236#ifdef DEBUG
237        printf("\nflashWriteDataRaw(0x%08"PRIx32", %p, 0x%"PRIx32")\n", addr, src, n_words);
238#endif
239
240        if ( 0 == n_words ) {
241                return 0;
242        }
243
244        if ( !b ) {
245                fprintf(stderr,"Missing bank descriptor argument\n");
246                return -1;
247        }
248        if ( !b->dd ) {
249                fprintf(stderr,"Bank descriptor not initialized\n");
250                return -1;
251        }
252
253        if ( addr & (FLASH_STRIDE(b)-1) ) {
254                fprintf(stderr,"Misaligned address (not on word boundary) 0x%08"PRIx32"\n", addr);
255                return -1;
256        }
257
258        if ( (sta = b->ops->check_ready(b, addr)) ) {
259                /* Error msgs have already been printed */
260                return addr;
261        }
262
263        bufsz = FLASH_NDEVS(b) * b->dd->bufsz;
264
265        then = BSP_flashBspOps.read_us_timer();
266
267        for ( f = 0, a = addr, s=src, i = n_words; i ; s+=N ) {
268                /* start of next buffer */
269                nxt = (a + bufsz) & ~(bufsz-1);
270
271                /* number of bytes */
272                N = (nxt - a);
273
274                if ( N > i * FLASH_STRIDE(b) )
275                        N = i * FLASH_STRIDE(b);
276
277                i -= N/FLASH_STRIDE(b);
278
279                if ( (sta = b->ops->write_line(b, a, s, N)) )
280                        goto bail;
281
282                if ( ! quiet && (now = BSP_flashBspOps.read_us_timer()) - then > 500000 ) {
283                        f = flip(f);
284                        then = now;
285                }
286
287                a = nxt;
288        }
289
290        sta = 0;
291
292        /* verify */
293        for ( i=0, a=addr; i < n_words * FLASH_STRIDE(b); i++, a++ ) {
294                if ( *(char*)a != src[i] ) {
295                        sta = -2;
296                        goto bail;
297                }
298        }
299
300bail:
301        if ( ! quiet ) {
302                wipe(f);
303        }
304        if ( sta ) {
305                switch ( sta ) {
306                        default:
307                                fprintf(stderr,"Error (flashWriteDataRaw): write error\n");
308                                b->ops->print_stat(b, sta,0);
309                        break;
310
311                        case -1:
312                                fprintf(stderr,"Error (flashWriteDataRaw): Timeout\n");
313                        break;
314
315                        case -2:
316                                fprintf(stderr,"Error (flashWriteDataRaw): write verification failed at 0x%08"PRIx32"\n", a);
317                        break;
318                }
319                b->ops->array_mode(b, a);
320        } else {
321                /* no errors */
322                a = 0;
323        }
324        return a;
325}
326
327
328/* Query device for basic information verifying that we talk
329 * to a 'known'/'supported' device.
330 *
331 * This is not really clean since (until we implement CFI)
332 * we already need to know what kind of device it is to
333 * be able to read its ID...
334 *
335 *   NOTES: - device switched back to array mode on exit.
336 *          - 'addr' must be 32-bit aligned.
337 */
338
339STATIC struct devdesc *
340BSP_flashCheckId(struct bankdesc *b, uint32_t addr, unsigned quiet)
341{
342uint8_t  x;
343uint32_t d;
344struct vendesc  *vd;
345struct devdesc  *dd;
346
347        /* check if it's flash at all: */
348        x = *(A8)addr;
349        *(A8)addr = ~x;
350        if ( x != *(A8)addr ) {
351                /* restore */
352                *(A8)addr = x;
353                if ( quiet < 3 )
354                        fprintf(stderr,"Addr 0x%08"PRIx32" seems to be RAM!\n", addr);
355                return 0;
356        }
357
358        if ( !(vd = knownVendor(b, addr, &d, quiet)) ) {
359                return 0;
360        }
361
362        /* Use the vendor ops for this bank */
363        b->ops    = vd->ops;
364
365        if ( !quiet )
366                printf("Flash device, vendor: %s", vd->name);
367
368        if ( !(dd = knownDevice(vd, d)) ) {
369                if ( !quiet )
370                        printf("\n");
371                if ( quiet < 2 )
372                        fprintf(stderr,"Unknown device id (0x%04"PRIx32") at 0x%08"PRIx32"\n",d, addr);
373                return 0;
374        }
375
376        /* logical sector size is device sector size
377         * multiplied by # of devices in parallel
378         */
379        b->fblksz = dd->fblksz * FLASH_NDEVS(b);
380
381        if ( !quiet )
382                printf(", device: %s -- size 0x%08"PRIx32" bytes\n", dd->name, dd->size);
383        return dd;
384}
385
386/* We don't have device info yet so just
387 * use 64k alignment
388 */
389#define SCAN_BACK_OFFSET        0x10000
390
391/* Scan address range for flash devices and compute total size
392 * of bank.
393 *
394 * RETURNS: size in bytes.
395 */
396STATIC uint32_t
397BSP_flashProbeSize(struct bankdesc *b)
398{
399int             max = b->max_size;
400uint32_t                rval;
401struct devdesc  *dd;
402unsigned                q;
403        if ( max > 0 ) {
404                for ( rval = 0, q=1; rval < max && (dd = BSP_flashCheckId(b, b->start + rval, q)); q=3 ) {
405                        rval += dd->size * FLASH_NDEVS(b);
406                }
407        } else {
408                /* bank is populated from the top; scan backwards */
409                max = -max;
410                for ( rval = 0, q=1; rval < max && (dd = BSP_flashCheckId(b, b->start + max - SCAN_BACK_OFFSET - rval, q)); q=3 ) {
411                        rval += dd->size * FLASH_NDEVS(b);
412                }
413                b->start += max - rval;
414        }
415        return rval;
416}
417
418uint32_t
419BSP_flashStart(int bank)
420{
421struct bankdesc *b;
422        if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
423                return -1;
424        return b->start;
425}
426
427uint32_t
428BSP_flashSize(int bank)
429{
430struct bankdesc *b;
431        if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
432                return -1;
433        return b->size;
434}
435
436uint32_t
437BSP_flashBlockSize(int bank)
438{
439struct bankdesc *b;
440        if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
441                return -1;
442        return b->fblksz;
443}
444
445
446#ifndef TESTING
447
448/* Obtain bank description making sure it is initialized and not write protected */
449STATIC struct bankdesc *
450bankValidate(int bank, int quiet)
451{
452struct bankdesc *b = BSP_flashBspOps.bankcheck(bank, quiet);
453
454        /* If flash is write-protected then we can't even talk to it... */
455        if ( BSP_flashBspOps.flash_wp(bank, -1) ) {
456                fprintf(stderr,"Flash bank #%i is write-protected; use 'BSP_flashWriteEnable(int bank)' and/or jumper\n", bank);
457                return 0;
458        }
459
460        if ( !b->dd && !(b->dd = BSP_flashCheckId(b, b->start,1)) ) {
461                fprintf(stderr,"Error: unable to detect flash device in bank #%i\n", bank);
462                return 0;
463        }
464        return b;
465}
466
467/* Validate arguments and write-protection status of 'bank'.
468 *
469 *    'bank': 0..max bank supported by board.
470 *  'offset': 0..bank size - 1
471 *     'src': src .. src + size - 1 must not overlap bank; 'src' may be NULL
472 *            (check is skipped in this case)
473 *
474 *      RETURNS: pointer to bank description on success, NULL on error (invalid args;
475 *               error message is printed to stderr).
476 *
477 * SIDE EFFECTS: probes for bank size and stores result in bank description table.
478 */
479
480static struct bankdesc *
481argcheck(int bank, uint32_t offset, char *src, uint32_t size)
482{
483struct bankdesc *b;
484
485        if ( !(b=bankValidate(bank, 0)) ) {
486                return 0;
487        }
488
489        if ( !b->size && !(b->size = BSP_flashProbeSize(b)) ) {
490                fprintf(stderr,"Configuration Error - unable to determine flash size\n");
491                return 0;
492        }
493        if ( offset + size > b->size ) {
494                fprintf(stderr,"Error: requested size exceeds available flash (0x%08"PRIx32" bytes)\n", b->size);
495                return 0;
496        }
497
498        if ( src && ( src + size > (char*)b->start && src < (char*)(b->start + b->size) ) ) {
499                fprintf(stderr,"Error: cannot copy data within flash bank\n");
500                return 0;
501        }
502
503
504        return b;
505}
506
507/* Calculate region that needs to be erased from 'offset' and 'n_bytes'
508 * handling alignment and checking for blank areas that need not be
509 * erased.
510 * Ask for user confirmation and erase calculated region.
511 *
512 * RETURNS: 0 on success, -1 or destination address on error.
513 *
514 *   NOTES: - device switched back to array mode on exit.
515 *          - prints progress/messages.
516 */
517STATIC int
518regionCheckAndErase(int bank, uint32_t offset, char *src, uint32_t n_bytes, int quiet)
519{
520struct bankdesc *b;
521uint32_t         i;
522char            *p;
523uint32_t                a,e;
524
525        if ( ! (b = argcheck(bank, offset, src, n_bytes)) )
526                return -1;
527
528        a = offset & ~(b->fblksz - 1);
529        e = (offset + n_bytes +  b->fblksz - 1) & ~ (b->fblksz - 1);
530
531        /* If 'offset' is not block-aligned then rest of the block must
532         * be free.
533         */
534        if ( a != offset ) {
535                a += b->fblksz;
536                i  = ( a > offset + n_bytes ) ? offset + n_bytes : a;
537                for ( p = (char*)(b->start + offset); p < (char*)(b->start + i); p++ ) {
538                        if ( (char)0xff != *p ) {
539                                if ( ! quiet ) {
540                                        fprintf(stderr,"Starting offset not block-aligned and destination area not empty.\n");
541                                        fprintf(stderr,"I'll need to erase data below destination start\n");
542                                }
543                                a -= b->fblksz;
544                                break;
545                        }
546                }
547        }
548        if ( e != offset + n_bytes ) {
549                e -= b->fblksz;
550                i  = ( e < offset ) ? offset : e;
551                for ( p = (char*)(b->start + i); p < (char*)(b->start + offset + n_bytes); p++ ) {
552                        if ( (char)0xff != *p ) {
553                                if ( ! quiet ) {
554                                        fprintf(stderr,"Ending offset not block-aligned and destination area not empty.\n");
555                                        fprintf(stderr,"I'll need to erase data beyond destination end\n");
556                                }
557                                e += b->fblksz;
558                                break;
559                        }
560                }
561        }
562        if ( ! quiet ) {
563                if ( e > a )
564                        printf("ERASING 0x%08"PRIx32" .. 0x%08"PRIx32"\n", (b->start+a), (b->start + e - 1));
565                printf("WRITING 0x%08"PRIx32" .. 0x%08"PRIx32"\n", (b->start+offset), (b->start + offset + n_bytes - 1));
566                printf("OK to proceed y/[n]?"); fflush(stdout);
567                if ( 'Y' != getUc() ) {
568                        printf("ABORTED\n");
569                        return -1;
570                }
571        }
572        if ( e > a ) {
573                if ( quiet < 2 ) {
574                        printf("ERASING  "); fflush(stdout);
575                }
576       
577                if ( (i = BSP_flashErase(bank, a, e-a, quiet ? quiet : 1)) )
578                        return i;
579
580                if ( quiet < 2 ) {
581                        printf("DONE\n");
582                }
583        }
584
585        return 0;
586}
587
588/* Write to a flash region ('offset'..'offset'+'n_bytes'-1 on 'bank').
589 *
590 * RETURNS: 0 on success, -1 or destination address on error.
591 *
592 *   NOTES: - device switched back to array mode on exit.
593 *          - no erase operation is performed.
594 *          - written data is verified against source.
595 */
596
597STATIC int
598BSP_flashWriteRegion(int bank, uint32_t offset, char *src, uint32_t n_bytes, int quiet)
599{
600struct bankdesc *b = BSP_flashBspOps.bankcheck(bank, 0);        /* caller did bankValidate() */
601uint32_t     ab = offset & ~(b->fblksz - 1);
602uint32_t     eb = (offset + n_bytes + b->fblksz - 1) & ~(b->fblksz - 1);
603uint32_t     o,i,a,e;
604int          err;
605char        *p;
606union bconv  buf;
607
608        /* unlock */
609        for ( i=ab; i<eb; i+=b->fblksz ) {
610                b->ops->unlock_block(b, b->start + i );
611        }
612
613        err = 0;
614        p = src;
615
616        /* handle misaligned offset merging old contents */
617        o = b->start + offset;
618        a = o & ~(FLASH_STRIDE(b)-1);
619        e = (o + n_bytes) & ~(FLASH_STRIDE(b)-1);
620
621        if ( o > a ) {
622                i = o - a;
623
624                rd_par(b, &buf, a);
625
626                while ( i < FLASH_STRIDE(b) && p < src + n_bytes ) {
627                        buf.c[i++] = *p++;
628                }
629                if ( (err = BSP_flashWriteDataRaw(b, a, buf.c, 1, quiet)) )
630                        goto bail;
631                a += FLASH_STRIDE(b);
632        }
633
634
635        /* caution if misaligned data covering only one or two words */
636
637        if ( e > a ) {
638                i = (e-a);
639                if ( (err = BSP_flashWriteDataRaw(b, a, p, i/FLASH_STRIDE(b), quiet)) )
640                        goto bail;
641                p += i;
642        }
643
644        /* handle misaligned end */
645        if ( o + n_bytes > e)  {
646                rd_par(b, &buf, e);
647                for ( i=0; p < src + n_bytes; ) {
648                        buf.c[i++] = *p++;
649                }
650                if ( (err = BSP_flashWriteDataRaw(b, e, buf.c, 1, quiet)) )
651                        goto bail;
652        }
653
654bail:
655        /* lock area */
656        for ( i=ab; i<eb; i+=b->fblksz ) {
657                b->ops->lock_block(b, b->start + i );
658        }
659
660        /* final verification */
661        if ( !err ) {
662                for ( i=0; i<n_bytes; i++ ) {
663                        if ( ((char*)(b->start + offset))[i] != src[i] ) {
664                                fprintf(stderr,"Final verification failed at offset 0x%08"PRIx32"\n", (offset + i));
665                                return b->start + offset + i;
666                        }
667                }
668        }
669
670        return err;
671}
672
673int
674BSP_flashErase(int bank, uint32_t offset, uint32_t size, int quiet)
675{
676struct bankdesc *b;
677uint32_t                 a,i;
678int              f;
679
680        if ( ! (b = argcheck(bank, offset, 0, size)) )
681                return -1;
682
683        if ( offset & (b->fblksz - 1) ) {
684                fprintf(stderr,"Offset misaligned (needs to be multiple of 0x%08"PRIx32")\n", b->fblksz);
685                return -1;
686        }
687        if ( size & (b->fblksz - 1) ) {
688                fprintf(stderr,"Size misaligned (needs to be multiple of 0x%08"PRIx32")\n", b->fblksz);
689                return -1;
690        }
691
692        a = b->start + offset;
693
694        if ( !quiet ) {
695                printf("ERASING Flash (Bank #%i)\n    from 0x%08"PRIx32" .. 0x%08"PRIx32"\nproceed y/[n]?",
696                        bank, a, (a+size-1));
697                fflush(stdout);
698                if ( 'Y' != getUc() ) {
699                        printf("ABORTED\n");
700                        return -1;
701                }
702        }
703        f = 0;
704        while ( size ) {
705                /* work to do ? */
706                for ( i = 0; i<b->fblksz; i++ ) {
707                        if ( (char)0xff != ((char*)a)[i] ) {
708                                b->ops->unlock_block(b, a);
709                                i = b->ops->erase_block(b, a);
710                                b->ops->lock_block(b, a);
711                                if (i) {
712                                        wipe(f);
713                                        return a;
714                                }
715                                break;
716                        }
717                }
718
719                if ( quiet < 2 ) {
720                        f = flip(f);
721                }
722               
723                a    += b->fblksz;
724                size -= b->fblksz;
725        }
726        b->ops->array_mode(b, a);
727        if ( quiet < 2 ) {
728                wipe(f);
729        }
730        return 0;
731}
732
733int
734BSP_flashWrite(int bank, uint32_t offset, char *src, uint32_t n_bytes, int quiet)
735{
736int      rval;
737
738        if ( !src ) {
739                fprintf(stderr,"Error: Data source pointer is NULL\n");
740                return -1;
741        }
742
743        if ( (rval = regionCheckAndErase(bank, offset, src, n_bytes, quiet)) )
744                return rval;
745
746        if ( ! quiet ) {
747                printf("WRITING  "); fflush(stdout);
748        }
749
750        rval = BSP_flashWriteRegion(bank, offset, src, n_bytes, quiet);
751
752        if ( !quiet && !rval ) {
753                printf("DONE");
754        }
755        if ( !quiet )
756                printf("\n");
757        return rval;
758}
759
760static int
761bfill(int fd, char *buf, int size)
762{
763int got, avail;
764        for (avail = size; (got = read(fd, buf, avail)) > 0; avail-=got ) {
765                buf  += got;
766        }
767        return size - avail;
768}
769
770int
771BSP_flashWriteFile(int bank, uint32_t offset, char *fname, int quiet)
772{
773int             fd   = -1;
774struct stat     sb;
775uint32_t            sz;
776int                         rval = -1;
777char               *buf  = 0;
778uint32_t            got;
779struct bankdesc *b;
780unsigned        f    = 0;
781
782        if ( ! (b = bankValidate(bank, 0)) )
783                return -1;
784
785        for ( sz = 0; -1 == fd ;  ) {
786                if ( (fd = open(fname,O_RDONLY)) < 0 ) {
787                        perror("Opening file");
788                        return -1;
789                }
790       
791                if ( sz )
792                        break;
793
794                if ( fstat(fd, &sb) ) {
795                        fprintf(stderr,"Warning: fstat doesn't work; need to slurp file to determine size; please be patient.\n");
796                        FILE *f;
797                        close(fd); fd = -1;
798                        f = fopen(fname,"r");
799                        if ( !f ) {
800                                perror("fdopen");
801                                return -1;
802                        }
803                        while ( EOF != fgetc(f) )
804                                sz++;
805                        fclose(f);
806                        /* reopen */
807                } else {
808                        sz = sb.st_size;
809                }
810                if ( 0 == sz ) {
811                        fprintf(stderr,"Error: zero file size (?)\n");
812                        goto bail;
813                }
814        }
815
816        if ( !(buf = malloc(b->fblksz)) ) {
817                perror("buffer allocation");
818                goto bail;
819        }
820
821        /* See if we can erase the entire region */
822        if ( (rval = regionCheckAndErase(bank, offset, buf, sz, quiet)) )
823                goto bail;
824
825        /* Proceed copying chunks */
826        if ( quiet < 2 ) {
827                printf("WRITING  "); fflush(stdout);
828        }
829
830        while ( (got = bfill(fd, buf, b->fblksz)) > 0 && sz ) {
831                if ( (rval = BSP_flashWriteRegion(bank, offset, buf, got, 1)) ) {
832                        wipe(f);
833                        goto bail;
834                }
835                offset += got;
836                sz     -= got;
837                if ( quiet < 2 ) {
838                        f = flip(f);
839                }
840        }
841        if ( got < 0 ) {
842                perror("reading file");
843                rval = offset;
844                goto bail;
845        }
846
847        if ( quiet < 2 ) {
848                wipe(f);
849                printf("DONE");
850        }
851bail:
852        if ( quiet < 2 ) {
853                printf("\n");
854        }
855        if ( fd > -1 )
856                close(fd);
857        free(buf);
858        return rval;
859}
860
861int
862BSP_flashWriteEnable(int bank)
863{
864        return BSP_flashBspOps.flash_wp(bank,0);
865}
866
867int
868BSP_flashWriteDisable(int bank)
869{
870        return BSP_flashBspOps.flash_wp(bank,1);
871}
872
873int
874BSP_flashDumpInfo(FILE *f)
875{
876struct bankdesc *b;
877int                     bank;
878
879        if ( !f )
880                f = stdout;
881
882        /* use 'bankValidate()' with 'quiet' flag to suppress error message when
883         * we reach the end of the table.
884         */
885        for ( bank = 0; BSP_flashBspOps.bankcheck(bank,1); bank++ ) {
886                if ( (b=argcheck(bank,0,0,0)) ) {
887                        fprintf(f,"Flash Bank #%i; 0x%08"PRIx32" .. 0x%08"PRIx32" (%"PRId32" bytes)\n",
888                                bank, b->start, (b->start + b->size - 1), b->size);
889                        fprintf(f,"%i * %i-bit devices in parallel; block size 0x%"PRIx32"\n", FLASH_NDEVS(b), FLASH_WIDTH(b)*8, b->fblksz);
890                        BSP_flashCheckId(b, b->start, 0);
891                }
892        }
893
894        return 0;
895}
896
897#else
898
899int
900main(int argc, char **argv)
901{
902uint32_t fla[1000];
903uint32_t qqq[1000];
904int i;
905        for ( i=0; i<sizeof(qqq)/sizeof(qqq[0]); i++ )
906                qqq[i] = 0xdada<<16 | i;
907        BSP_flashWriteDataRaw(0, (uint32_t)fla, (char*)qqq, 32, 0);
908}
909#endif
Note: See TracBrowser for help on using the repository browser.