From: Erik M. <er...@us...> - 2001-12-31 00:28:56
|
Update of /cvsroot/blob/blob/src/blob In directory usw-pr-cvs1:/tmp/cvs-serv31353/src/blob Modified Files: flash.c Log Message: Flesh out the lock/unlock and query lock functions. Add some more comments to the header file. Index: flash.c =================================================================== RCS file: /cvsroot/blob/blob/src/blob/flash.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- flash.c 2001/12/16 07:36:42 1.9 +++ flash.c 2001/12/31 00:28:53 1.10 @@ -329,3 +329,186 @@ return 0; } + + + + +/* given an address, return the flash block index number (or negative + * error number otherwise + */ +static int find_block(u32 address) +{ + int i; + + for (i = 0; i < num_flash_blocks; i++) { + u32 start = flash_blocks[i].start; + int length = flash_blocks[i].size; + u32 endIncl = start + length - 1; + + if (address >= start && address <= endIncl) + return i; + } + + return -ERANGE; +} + + + + +/* convert address range to range of flash blocks. returns 0 on + * success or negative error number on failure. + */ +static int address_range_to_block_range(u32 startAddress, int length, + int *startBlock, int *endInclBlock) +{ + int sb, eib; + +#ifdef FLASH_DEBUG + SerialOutputString(__FUNCTION__ ": startAddress = 0x"); + SerialOutputHex(startAddress); + SerialOutputString(", length = 0x"); + SerialOutputHex(length); + SerialOutputString("\n"); +#endif + + sb = find_block(startAddress); + eib = find_block(startAddress + length - 1); + + if(sb < 0) + return sb; + + if(eib < 0) + return eib; + +#ifdef FLASH_DEBUG + SerialOutputString("sb: "); + SerialOutputDec(sb); + SerialOutputString(", eib: "); + SerialOutputDec(eib); + SerialOutputString("\n"); +#endif + + // would be nice to warn if sb isn't at the beginning of + // its block or eib isn't at the very end of its block. + + *startBlock = sb; + *endInclBlock = eib; + + return 0; +} + + + + +static int do_flash_lock(u32 *start, u32 nwords, int lock) +{ + int sb, eib; + int rv; + int i; + u32 *addr; + +#ifdef BLOB_DEBUG + SerialOutputString(__FUNCTION__ "(): "); + if(lock == 0) + SerialOutputString("un"); + + SerialOutputString("lock at 0x"); + SerialOutputHex((u32)start); + SerialOutputString(", nwords = 0x"); + SerialOutputHex(nwords); + SerialOutputByte('\n'); +#endif + + rv = address_range_to_block_range((u32) start, nwords * sizeof(u32), + &sb, &eib); + + if(rv < 0) + return rv; + + /* check if it is lockable at all */ + for(i = sb; i <= eib; i++) { + if(!flash_blocks[i].lockable) { +#ifdef BLOB_DEBUG + printerrprefix(); + SerialOutputString("can't (un)lock unlockable blocks\n"); +#endif + return -EFLASHPGM; + } + } + + flash_driver->enable_vpp(); + + for(i = sb; i <= eib; i++) { + addr = (u32 *)flash_blocks[i].start; + + if(lock) + rv = flash_driver->lock_block(addr); + else + rv = flash_driver->unlock_block(addr); + + if(rv < 0) { + flash_driver->disable_vpp(); +#ifdef BLOB_DEBUG + printerrprefix(); + SerialOutputString("can't (un)lock block at 0x"); + SerialOutputHex((u32)addr); + SerialOutputByte('\n'); +#endif + return rv; + } + } + + flash_driver->disable_vpp(); + + return 0; +} + + + + +int flash_lock_region(u32 *start, u32 nwords) +{ + return do_flash_lock(start, nwords, 1); +} + + + + +int flash_unlock_region(u32 *start, u32 nwords) +{ + return do_flash_lock(start, nwords, 0); +} + + + + +/* return number of blocks in the region locked, 0 if everything is + * unlocked, or negative error number otherwise */ +int flash_query_region(u32 *start, u32 nwords) +{ + int sb, eib, rv, i; + int cnt = 0; + u32 *addr; + + rv = address_range_to_block_range((u32) start, nwords * sizeof(u32), + &sb, &eib); + + if(rv < 0) + return rv; + + for(i = sb; i <= eib; i++) { + addr = (u32 *)flash_blocks[i].start; + + if(flash_blocks[i].lockable) { + rv = flash_driver->query_block_lock(addr); + + if(rv < 0) + return rv; + + if(rv > 0) + cnt++; + } + } + + return cnt; +} |