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;
+}
|