?? blkmem.c
字號:
#endif if (failures > 0) { printk("FLASH: %d failures programming FLASH!\n", failures); return; }#if 0 printk("\nFLASH: programming successful!\n");#endif if (prog->reset) { printk("FLASH: rebooting...\n\n"); HARD_RESET_NOW(); }}#endif /* defined(CONFIG_INTELFLASH) *//****************************************************************************/#endif /* CONFIG_FLASH_SNAPGEAR *//****************************************************************************/#ifdef CONFIG_SHGLCOREstatic DECLARE_MUTEX(spare_lock);void read_spare(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer){#ifdef DEBUG printk("rsl\n");#endif /* Mutex all access to FLASH */ down(&spare_lock); #ifdef DEBUG printk("rsld\n");#endif /* Just copy the data into target buffer */ memcpy( buffer, (void*)(a->address+pos), length); /* Release MUTEX */ up(&spare_lock); #ifdef DEBUG printk("rsud\n");#endif}void write_spare(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer){ unsigned long start; unsigned char c; volatile unsigned char * address; unsigned char result; unsigned long fbase = a->address; unsigned long flags; #if 0 for(i = pos / a->blksize; i <= ((pos+length-1) / a->blksize); i++) { if (test_bit(i, &a->auto_erase_bits)) { /* erase sector start */ printk("Autoerase of sector %d\n", i); erase_spare(a, i * a->blksize); clear_bit(i, &a->auto_erase_bits); } }#endif#ifdef DEBUG printk("wsl\n");#endif down(&spare_lock); #ifdef DEBUG printk("wsld\n");#endif start = jiffies; address = (unsigned volatile char*)(fbase+pos); while (length>0) { c = *buffer++; /*printk("Checking spare_flash program of byte %lx, at address %p, value %x (%c), current %x (%c)\n", pos, address, c, c, *address, *address);*/ if (*address != c) { /*printk("Starting spare_flash program of byte %lx, at address %p\n", pos, address);*/ if (c & ~*address) { printk("Unable to write byte at %p (impossible bit transition in %x, actual %x)\n", address, c, *address); /*continue;*/ } save_flags(flags); cli(); *(unsigned volatile char *)(fbase | 0x5555)=0x0aa; *(unsigned volatile char *)(fbase | 0x2aaa)=0x055; *(unsigned volatile char *)(fbase | 0x5555)=0x0a0; *address = c; for(;;) { result = *address; /*printk("Read value %x (%c)\n", result, result);*/ if ((result & 0x80) == (c & 0x80)) break; if (result & 0x20) { printk("timeout of FLASH write at address %p of value %x (actual %x)\n", address, c, *address); *(unsigned volatile char *)(fbase)=0x0f0; /* Reset */ break; } } restore_flags(flags); /*printk("Completed spare_flash program of byte %lx, at address %p\n", pos, address);*/ #if 0 if (jiffies != start) { /*printk("Spare_flash rescheduling in write\n");*/ current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies; schedule(); current->timeout = 0; /*schedule();*/ start = jiffies; }#endif } address++; length--; } up(&spare_lock); #ifdef DEBUG printk("wsud\n");#endif}void erase_spare(struct arena_t * a, unsigned long pos){ unsigned long fbase = a->address; int delay; unsigned volatile char * address; unsigned long flags; if (pos >= a->length) return; /* Mutex all access to FLASH memory */ #ifdef DEBUG printk("esl\n");#endif down(&spare_lock);#ifdef DEBUG printk("esld\n");#endif address = (unsigned volatile char*)(fbase + pos); printk("Starting spare_flash erase of byte %lx, at address %p\n", pos, address); save_flags(flags); cli();again: delay = HZ/4+1; /* Initiate erase of FLASH sector */ *(unsigned volatile char *)(fbase | 0x5555)=0x0aa; *(unsigned volatile char *)(fbase | 0x2aaa)=0x055; *(unsigned volatile char *)(fbase | 0x5555)=0x080; *(unsigned volatile char *)(fbase | 0x5555)=0x0aa; *(unsigned volatile char *)(fbase | 0x2aaa)=0x055; *address = 0x030; /* Delay until erase is complete */ for (;;) { unsigned char result;#ifdef original_spare_erase_delay struct wait_queue *wait = NULL;#ifdef DEBUG printk("Spare_flash erase delaying for %d ticks, status is %x\n", delay, (unsigned int)*address);#endif current->timeout = jiffies + delay;#if 0 current->state = TASK_INTERRUPTIBLE; schedule(); current->timeout = 0;#endif interruptible_sleep_on(&wait);#endif udelay(100000); result = *address; if (result & 0x80) break; if (result & 0x20) { printk("timeout of Spare_flash erase of address %p\n", address); *(unsigned volatile char *)(fbase)=0x0f0; /* Reset */ printk("Sleeping a second and retrying\n"); udelay(1000000); goto again; } } restore_flags(flags);#ifdef DEBUG printk("Completed spare_flash erase of byte %lx, at address %p\n", pos, address);#endif up(&spare_lock);#ifdef DEBUG printk("esud\n");#endif}#define VSP(X) (*(volatile unsigned short *)(X))#define VSC(X) (*(volatile unsigned char *)(X))#define SCSR VSP(0xfffc0c)#define SCSR_TDRE (1<<8)#define SCDR VSP(0xfffC0e)#define print_char(x) ({ \ while (!(SCSR & SCSR_TDRE)) \ ; \ SCDR = (x); \})#define print_hexdigit(x) ({ \ int digit = (x) & 0xf; \ if (digit>9) \ print_char('a'+digit-10); \ else \ print_char('0'+digit); \ \})#define print_num(x) ({ \ unsigned long num = (x); \ print_hexdigit(num >> 28); \ print_hexdigit(num >> 24); \ print_hexdigit(num >> 20); \ print_hexdigit(num >> 16); \ print_hexdigit(num >> 12); \ print_hexdigit(num >> 8); \ print_hexdigit(num >> 4); \ print_hexdigit(num >> 0); \})/* Note: sub_program_main must not reference _any_ data or code outside of itself, or leave interrupts enabled, due to the fact that it is probably erasing & reloading the kernel. */#define SET_SHORT(x,y) VSP((x)) = (y)/*#define SET_SHORT(x,y) ({})*/ /*print_char('>');print_num(x);*/ /*printk("%8.8lx <= %04x\n", (x), (y))*/#define SET_CHAR(x,y) VSC((x)) = (y)/*#define SET_CHAR(x,y) ({})*/ /*print_char('>');print_num(x);*/ /*printk("%8.8lx <= %02x\n", (x), (y))*/#define GET_SHORT(x) VSP((x))/*#define GET_SHORT(x) ({0;})*/ /*({print_char('<');print_num(x);0;})*/ /*(printk("%8.8lx => ....\n", (x)),0)*/#define GET_CHAR(x) VSC((x))/*#define GET_CHAR(x) ({0;})*/ /*({print_char('<');print_num(x);0;})*/ /*(printk("%8.8lx => ..\n", (x)),0)*/void sub_program_main(struct arena_t * a, struct blkmem_program_t * prog){ volatile int i,l; unsigned long base, offset, ptr, min, max; unsigned char * c; unsigned int erased = 0; int failures; int retry; cli(); retry = 0;again: SET_ALARM_LED(1); retry++; if (retry>5) { goto give_up; } print_char('\r'); print_char('\n'); print_char('R'); print_char('0' + retry); failures = 0; erased = 0; /* for(i=prog->blocks-1;i>=0;i--) {*/ for(i=0;i<prog->blocks;i++) { SET_COMM_STATUS_LED(!GET_COMM_STATUS_LED()); print_char('\r'); print_char('\n'); print_num(prog->block[i].pos+a->address); print_char('-'); print_num(prog->block[i].pos+prog->block[i].length-1+a->address); print_char('\r'); print_char('\n'); if(prog->block[i].length > 0xE0000) break; for(l=prog->block[i].pos / a->blksize; l <= ((prog->block[i].pos+prog->block[i].length-1) / a->blksize); l++) { if (!test_bit(l, &erased)) { print_char('E'); print_char('0' + l / 10); print_char('0' + l % 10); print_char('\r'); print_char('\n'); if (l < 1) break; /*if (l >= 8) break;*/ ptr = l * a->blksize; offset = ptr % a->unitsize; base = ptr - offset; base += a->address; ptr += a->address; print_char('b'); print_char('a'); print_char('s'); print_char('e'); print_char(' '); print_num(base); print_char('\r'); print_char('\n'); print_char('o'); print_char('f'); print_char('f'); print_char(' '); print_num(offset); print_char('\r'); print_char('\n'); print_char('p'); print_char('t'); print_char('r'); print_char(' '); print_num(ptr); print_char('\r'); print_char('\n'); set_bit(l, &erased); if (ptr < 0x020000) break; /*if (ptr >= 0x100000) break;*/ print_num(ptr); SET_COMM_ERROR_LED(1); /* Erase even half of sector */ SET_SHORT( (base | (0x5555 << 1)), 0xaa00); SET_SHORT( (base | (0x2aaa << 1)), 0x5500); SET_SHORT( (base | (0x5555 << 1)), 0x8000); SET_SHORT( (base | (0x5555 << 1)), 0xaa00); SET_SHORT( (base | (0x2aaa << 1)), 0x5500); SET_SHORT( ptr, 0x3000);#ifdef original_erase_logic while (!(GET_SHORT(ptr) & 0x8000)) ;#else for (;;) { unsigned int status = GET_SHORT(ptr); if (status & 0x8000) { /* Erase complete */ break; } if (status & 0x2000) { /* Check again */ status = GET_SHORT(ptr); if (status & 0x8000) { /* Erase complete */ break; } /* Erase failed */ print_char('F'); /* Reset FLASH unit */ SET_SHORT( base, 0xf000); failures++; /* Continue (with unerased sector) */ break; } }#endif print_char(':'); /* Erase odd half of sector */ SET_SHORT( (base | (0x5555 << 1)), 0x00aa); SET_SHORT( (base | (0x2aaa << 1)), 0x0055); SET_SHORT( (base | (0x5555 << 1)), 0x0080); SET_SHORT( (base | (0x5555 << 1)), 0x00aa); SET_SHORT( (base | (0x2aaa << 1)), 0x0055); SET_SHORT( ptr, 0x0030);#ifdef original_erase_logic while (!(GET_SHORT(ptr) & 0x0080)) ;#else for (;;) { unsigned int status = GET_SHORT(ptr); if (status & 0x0080) { /* Erase complete */ break; } if (status & 0x0020) { /* Check again */ status = GET_SHORT(ptr); if (status & 0x0080) { /* Erase complete */ break; } /* Erase failed */ print_char('F'); /* Reset FLASH unit */ SET_SHO
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -