?? flash.c
字號:
/* flashcom.c: * This file contains the portions of the flash code that are device * independent. Refer to the appropriate device sub-directory for the * code that is specific to the flash device on the target. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#if INCLUDE_FLASH//#include "cpu.h"#include "flashdev.h"#include "flash.h"#include "genlib.h"#include "ctype.h"#include "stddefs.h"#include "tfs.h"//#include "cli.h"extern struct flashdesc FlashNamId[];int FlashCurrentBank;int sectortoaddr(int,int *,uchar **);#define SRANGE_ERROR -1#define SRANGE_SINGLE 1#define SRANGE_RANGE 2#define SRANGE_ALL 3 /* FlashProtectWindow: * Must be set to allow any flash operation to be done on space assumed * to be software protected. */int FlashProtectWindow;/* FlashBank[]: * This table contains all of the information that is needed to keep the * flash code somewhat generic across multiple flash devices. */struct flashinfo FlashBank[FLASHBANKS];#ifdef DISABLE_INTERRUPTS_DURING_FLASHOPS#define FLASH_INTSOFF() intsoff()#define FLASH_INTSRESTORE(ival) intsrestore(ival)#else#define FLASH_INTSOFF() 0#define FLASH_INTSRESTORE(ival)#endif/* showflashtype(): * Find a match between the incoming id and an entry in the FlashNamId[] * table. The FlashNamId[] table is part of the device-specific code. */intshowflashtype(ulong id){ struct flashdesc *fdp; fdp = FlashNamId; while(fdp->desc) { if (id == fdp->id) { printf("Device = %s\n",fdp->desc); return(0); } fdp++; } printf("Flash id 0x%lx not recognized\n",id); return(-1);}/* flasherased(): * Return 1 if range of memory is all 0xff; else 0. * Scan through the range of memor specified by begin-end (inclusive) * looking for anything that is not 0xff. Do this in three sections so * that the pointers can be 4-byte aligned for the bulk of the comparison * range... * The beginning steps through as a char pointer until aligned on a 4-byte * boundary. Then do ulong * comparisons until the just before the end * where we once again use char pointers to align on the last few * non-aligned bytes (if any). */intflasherased(uchar *begin, uchar *end){ ulong *lp, *lp1; /* Get pointers aligned so that we can do the bulk of the comparison * with long pointers... */ while(((long)begin & 3) && (begin != end)) { if (*begin != 0xff) { return(0); } begin++; } if (begin >= end) return(1); lp = (ulong *)begin; lp1 = (ulong *)end; (long)lp1 &= ~3; while(lp < lp1) { if (*lp != 0xffffffff) { return(0); } lp++; } if (lp >= (ulong *)end) return(1); begin = (uchar *)lp; do { if (*begin++ != 0xff) return(0); } while(begin != end); return(1);}/* showflashinfo(): * Dump information about specified flash device. */intshowflashinfo(struct flashinfo *fdev, char *range){ int i; struct sectorinfo *sp; if (showflashtype(fdev->id) < 0) return(-1); printf(" Base addr : 0x%08lx\n",(ulong)(fdev->base)); printf(" Sectors : %d\n",fdev->sectorcnt); printf(" Bank width : %d\n",fdev->width); printf(" Sector Begin End Size SWProt? Erased?\n"); for(i=0;i<fdev->sectorcnt;i++) { sp = &fdev->sectors[i]; if (inRange(range,sp->snum)) { printf(" %2d 0x%08lx 0x%08lx 0x%06lx %s %s\n", sp->snum, (ulong)(sp->begin), (ulong)(sp->end), sp->size, sp->protected ? "yes" : " no", flasherased(sp->begin,sp->end) ? "yes" : "no"); } } return(0);}/* flashopload(): * Copy flash operation to ram space. * Note that this function assumes that cache is disabled at this point. * This is important because we are copying text into bss space and if * cache was on, there could be a coherency problem. */intflashopload(ulong *begin,ulong *end,ulong *copy,int size){ volatile ulong *bp; int ret; /* Verify space availability: */ if (((int)end - (int)begin) >= size) { printf("flashopload overflow ((0x%lx-0x%lx) > 0x%x)\n", (ulong)end,(ulong)begin,size); return(-1); } ret = 0; /* Copy function() to RAM, then verify: */ bp = begin; while(bp <= end) { *copy = *bp; if (*copy++ != *bp++) { printf("flashopload failed\n"); ret = -1; break; } } return(ret);}/* flashtype(): * Use the device-specific function pointer to call the routine * relocated to RAM space. */intflashtype(fdev)struct flashinfo *fdev;{ return(fdev->fltype(fdev));}/* flasherase(): * Use the device-specific function pointer to call the routine * relocated to RAM space. * Note that flasherase() is called with a sector number. The sector * number is relative to the entire system, not just the particular device. * This means that if there is more than one flash device in the system that * the actual sector number (relative to the device) may not be the same * value. This adjustment is made here so that the underlying code that is * pumped into ram for execution does not have to be aware of this. */intflasherase(fdev,snum)struct flashinfo *fdev;int snum;{ int size; unsigned char *base, *end; if (fdev->id == FLASHRAM) { if (snum == ALL_SECTORS) { size = fdev->end - fdev->base; base = fdev->base; } else { sectortoaddr(snum,&size,&base); } end = base+size; while(base < end) { *base = 0xff; if (*base++ != 0xff) return(-1); } return(0); } if ((snum != ALL_SECTORS) && (fdev->sectors[0].snum != 0)) {/* printf("Adjusting snum from %d to",snum); */ snum -= fdev->sectors[0].snum;/* printf(" %d.\n",snum); */ } return(fdev->flerase(fdev,snum));}/* flashwrite(): * Use the device-specific function pointer to call the routine * relocated to RAM space. * First make a few checks on the request, then write to flash if all * checks succeed. */intflashwrite(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt){ int j, lowsector, highsector; register uchar *dp, *sp, *edp; if (fdev->id == FLASHRAM) { uchar *sp, *dp, *end; sp = src; dp = dest; end = dp+bytecnt; while(dp < end) { *dp = *sp; if (*dp != *sp) return(-1); dp++; sp++; } return(0); } dp = dest; sp = src; edp = (dest + bytecnt) - 1; /* If outside the devices space, return failed.. */ if ((edp < fdev->sectors[0].begin) || (dp > fdev->sectors[fdev->sectorcnt-1].end)) { printf("flashwrite() failed: dest out of flash range\n"); return(-1); } /* Make sure the destination is not within a protected sector */ if (FlashProtectWindow == FLASH_PROTECT_WINDOW_CLOSED) { /* First determine the sectors that overlap with the * flash space to be written... */ lowsector = highsector = -1; for(j=0;j<fdev->sectorcnt;j++) { if ((dp >= fdev->sectors[j].begin) && (dp <= fdev->sectors[j].end)) lowsector = j; } for(j=0;j<fdev->sectorcnt;j++) { if ((edp >= fdev->sectors[j].begin) && (edp <= fdev->sectors[j].end)) highsector = j; } if ((lowsector == -1) || (highsector == -1)) { printf("flashwrite() failed: can't find sector\n"); return(-1); } /* Now that the range of affected sectors is known, * verify that those sectors are not protected... */ for(j=lowsector;j<=highsector;j++) { if (fdev->sectors[j].protected) { printf("flashwrite() failed: sector protected\n"); return(-1); } } } /* Now make sure that there is no attempt to transition a bit * in the affected range from 0 to 1... A flash write can only * bring bits low (erase brings them high). */ while(dp < edp) { if ((*dp & *sp) != *sp) { printf("flashwrite() failed: bit 0->1 rqst denied.\n"); return(-1); } dp++; sp++; } return(fdev->flwrite(fdev,dest,src,bytecnt));}/* flashewrite(): * Use the device-specific function pointer to call the routine * relocated to RAM space. */intflashewrite(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt){ int i; /* Source and destination addresses must be long-aligned. */ if (((int)src & 3) || ((int)dest & 3)) return(-1); /* If the protection window is closed, then verify that no protected * sectors will be written over... */ if (FlashProtectWindow == FLASH_PROTECT_WINDOW_CLOSED) { for (i=0;i<fdev->sectorcnt;i++) { if((((uchar *)dest) > (fdev->sectors[i].end)) || (((uchar *)dest+bytecnt) < (fdev->sectors[i].begin))) continue; else if (fdev->sectors[i].protected) return(-1); } } return(fdev->flewrite(fdev,dest,src,bytecnt));}/* addrtosector(): * Incoming address is translated to sector number, size of sector * and base of sector. * Return 0 if successful; else -1. */intaddrtosector(uchar *addr,int *sector,int *size,uchar **base){ struct flashinfo *fbnk; struct sectorinfo *sinfo; int dev, sec, i; sec = 0; for(dev=0;dev<FLASHBANKS;dev++) { fbnk = &FlashBank[dev]; for(i=0;i<fbnk->sectorcnt;i++,sec++) { sinfo = &fbnk->sectors[i]; if ((addr >= sinfo->begin) && (addr <= sinfo->end)) { if (sector) { *sector = sec; } if (base) { *base = sinfo->begin; } if (size) { *size = sinfo->size; } return(0); } } } printf("addrtosector(0x%lx) failed\n",(ulong)addr); return(-1);}/* addrtobank(): * From the incoming address, return a pointer to the flash bank that * this address is within. */struct flashinfo *addrtobank(uchar *addr){ struct flashinfo *fbnk; int dev; for(dev=0;dev<FLASHBANKS;dev++) { fbnk = &FlashBank[dev]; if ((addr >= fbnk->base) && (addr <= fbnk->end)) return(fbnk); } printf("addrtobank(0x%lx) failed\n",(ulong)addr); return(0);}int
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -