joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers support_funcs.c Source File

support_funcs.c

00001 /*
00002  * Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "support_funcs.h"
00019 #include <string.h>
00020 #include <stdio.h>
00021 #include <inttypes.h>
00022 
00023 static inline int32_t mtdGetStartAddr(ARM_DRIVER_STORAGE *mtd, uint64_t *startAddrP)
00024 {
00025     ARM_STORAGE_BLOCK mtdBlock;
00026     if ((mtd->GetNextBlock(NULL, &mtdBlock)) != ARM_DRIVER_OK) {
00027         return JOURNAL_STATUS_STORAGE_API_ERROR;
00028     }
00029     if (!ARM_STORAGE_VALID_BLOCK(&mtdBlock)) {
00030         return JOURNAL_STATUS_ERROR;
00031     }
00032 
00033     *startAddrP = mtdBlock.addr;
00034     return JOURNAL_STATUS_OK;
00035 }
00036 
00037 int32_t discoverLatestLoggedBlob(SequentialFlashJournal_t *journal)
00038 {
00039     int32_t rc;
00040 
00041     /* reset top level journal metadata prior to scanning headers. */
00042     journal->nextSequenceNumber       = SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER; /* we are currently unaware of previously written blobs */
00043     journal->currentBlobIndex         = SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS;
00044     journal->info.sizeofJournaledBlob = 0;
00045 
00046     /* begin header-scan from the first block of the MTD */
00047     ARM_DRIVER_STORAGE *mtd = journal->mtd;
00048     if ((rc = mtdGetStartAddr(journal->mtd, &journal->mtdStartOffset)) != JOURNAL_STATUS_OK) {
00049         return rc;
00050     }
00051     journal->initScan.currentOffset = journal->mtdStartOffset;
00052     journal->state                  = SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS;
00053 
00054     // printf("start of init scan\n");
00055     for (unsigned blobIndex = 0;
00056          blobIndex < SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS;
00057          blobIndex++, journal->initScan.currentOffset += journal->sequentialSkip) {
00058         // printf("blob index %u\n", blobIndex);
00059         /* TODO: it is possible that the header structure spans multiple blocks, needing multiple reads. */
00060 
00061         if (((rc = mtd->ReadData(journal->initScan.currentOffset, &journal->initScan.head, sizeof(SequentialFlashJournalLogHead_t))) < ARM_DRIVER_OK) ||
00062             (rc != sizeof(SequentialFlashJournalLogHead_t))) {
00063             /* TODO: add support for asynchronous scan */
00064             if ((rc == ARM_DRIVER_OK) && (journal->mtdCapabilities.asynchronous_ops)) {
00065                 return JOURNAL_STATUS_UNSUPPORTED;
00066             }
00067 
00068             return JOURNAL_STATUS_STORAGE_IO_ERROR;
00069         }
00070         // printf("head->version: %lu\n", journal->initScan.head.version);
00071         // printf("head->magic: %lx\n", journal->initScan.head.magic);
00072         // printf("head->sequenceNumber: %lu\n", journal->initScan.head.sequenceNumber);
00073         // printf("head->reserved: %lu\n", journal->initScan.head.reserved);
00074 
00075         if (SEQUENTIAL_JOURNAL_VALID_HEAD(&journal->initScan.head)) {
00076             journal->initScan.headSequenceNumber = journal->initScan.head.sequenceNumber;
00077             // printf("found valid header with sequenceNumber %lu\n", journal->initScan.headSequenceNumber);
00078 
00079             uint64_t tailoffset = journal->initScan.currentOffset
00080                                   - ((journal->initScan.currentOffset - journal->mtdStartOffset) % journal->sequentialSkip)
00081                                   + journal->sequentialSkip
00082                                   - sizeof(SequentialFlashJournalLogTail_t);
00083 
00084             // printf("hoping to read a tail at offset %lu\n", (uint32_t)tailoffset);
00085             if (((rc = mtd->ReadData(tailoffset, &journal->initScan.tail, sizeof(SequentialFlashJournalLogTail_t))) < ARM_DRIVER_OK) ||
00086                 (rc != sizeof(SequentialFlashJournalLogTail_t))) {
00087                 return JOURNAL_STATUS_STORAGE_IO_ERROR;
00088             }
00089 
00090             if (SEQUENTIAL_JOURNAL_VALID_TAIL(&journal->initScan.tail) &&
00091                 (journal->initScan.tail.sequenceNumber == journal->initScan.headSequenceNumber)) {
00092                 // printf("found valid blob with sequence number %lu\n", journal->initScan.headSequenceNumber);
00093                 uint32_t nextSequenceNumber = journal->initScan.headSequenceNumber + 1;
00094                 if (nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) {
00095                     nextSequenceNumber = 0;
00096                 }
00097 
00098                 if ((journal->nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) ||
00099                     /* We take advantage of properties of unsigned arithmetic in the following
00100                      * expression.
00101                      *
00102                      * We want to calculate if (nextSequenceNumber > journal->nextSequenceNumber),
00103                      * instead we use the expression ((nextSequenceNumber - journal->nextSequenceNumber) > 0)
00104                      * to take wraparounds into account.
00105                      */
00106                     ((int32_t)(nextSequenceNumber - journal->nextSequenceNumber) > 0)) {
00107                     journal->currentBlobIndex         = blobIndex;
00108                     journal->nextSequenceNumber       = nextSequenceNumber;
00109                     journal->info.sizeofJournaledBlob = journal->initScan.tail.sizeofBlob;
00110                     // printf("discoverLatestLoggedBlob: index %lu, sizeofBlob: %lu, nextSequenceNumber: %lu\n",
00111                     //        journal->currentBlobIndex, (uint32_t)journal->info.sizeofJournaledBlob, journal->nextSequenceNumber);
00112                 }
00113             }
00114         }
00115     }
00116     // printf("finished init scan\n");
00117 
00118     /* Handle the case where our scan hasn't yielded any results. */
00119     if (journal->nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) {
00120         // printf("discoverLatestLoggedBlob: initializing to defaults\n");
00121         journal->currentBlobIndex   = (uint32_t)-1; /* to be incremented to 0 during the first attempt to log(). */
00122         journal->nextSequenceNumber = 0;
00123 
00124         /* setup info.current_program_unit */
00125         ARM_STORAGE_BLOCK storageBlock;
00126         if ((rc = journal->mtd->GetBlock(journal->mtdStartOffset, &storageBlock)) != ARM_DRIVER_OK) {
00127             return JOURNAL_STATUS_STORAGE_API_ERROR;
00128         }
00129     }
00130 
00131     journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00132 
00133     return JOURNAL_STATUS_OK;
00134 }
00135 
00136 int32_t flashJournalStrategySequential_reset_progress(void)
00137 {
00138     int32_t rc;
00139     SequentialFlashJournal_t *journal = activeJournal;
00140 
00141     if (journal->mtdCapabilities.erase_all) {
00142         if ((rc = journal->mtd->EraseAll()) < ARM_DRIVER_OK) {
00143             journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00144             return JOURNAL_STATUS_STORAGE_IO_ERROR;
00145         }
00146         if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) {
00147             return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */
00148         }
00149         /* else we fall through to handle synchronous completion */
00150     } else {
00151         if ((rc = journal->mtd->Erase(journal->mtdStartOffset, SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS * journal->sequentialSkip)) < ARM_DRIVER_OK) {
00152             journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00153             return JOURNAL_STATUS_STORAGE_IO_ERROR;
00154         }
00155         if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) {
00156             printf("eturning JOURNAL_STATUS_OK\n");
00157             return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */
00158         }
00159         /* else we fall through to handle synchronous completion */
00160     }
00161 
00162     journal->nextSequenceNumber       = 0;
00163     journal->currentBlobIndex         = (uint32_t)-1;
00164     journal->info.sizeofJournaledBlob = 0;
00165     journal->state                    = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00166     return 1;
00167 }
00168 
00169 int32_t flashJournalStrategySequential_read_progress(void)
00170 {
00171     SequentialFlashJournal_t *journal = activeJournal;
00172 
00173     // printf("flashJournalStrategySequential_read_progress\n");
00174     if (journal->state != SEQUENTIAL_JOURNAL_STATE_READING) {
00175         return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00176     }
00177 
00178     int32_t rc;
00179     ARM_STORAGE_BLOCK storageBlock;
00180 
00181     if ((journal->read.amountLeftToRead) &&
00182         ((rc = journal->mtd->GetBlock(journal->read.offset, &storageBlock)) != ARM_DRIVER_OK)) {
00183         journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00184         return JOURNAL_STATUS_STORAGE_API_ERROR;
00185     }
00186     uint64_t storageBlockAvailableCapacity = storageBlock.size - (journal->read.offset - storageBlock.addr);
00187 
00188     while (journal->read.amountLeftToRead) {
00189         while (!storageBlockAvailableCapacity) {
00190             if ((rc = journal->mtd->GetNextBlock(&storageBlock, &storageBlock)) < ARM_DRIVER_OK) {
00191                 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00192                 return JOURNAL_STATUS_ERROR; /* We ran out of storage blocks. Journal is in an un-expected state. */
00193             }
00194             journal->read.offset          =  storageBlock.addr; /* This should not be necessary since we assume
00195                                                                  * storage map manages a contiguous address space. */
00196             storageBlockAvailableCapacity = storageBlock.size;
00197         }
00198 
00199         /* compute the transfer size for this iteration. */
00200         uint32_t xfer = (journal->read.amountLeftToRead < storageBlockAvailableCapacity) ?
00201                             journal->read.amountLeftToRead : storageBlockAvailableCapacity;
00202 
00203         /* perform the IO */
00204         //printf("reading %lu bytes at offset %lu\n", xfer, (uint32_t)journal->read.offset);
00205         rc = journal->mtd->ReadData(journal->read.offset, journal->read.dataBeingRead, xfer);
00206         if (rc < ARM_DRIVER_OK) {
00207             journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00208             return JOURNAL_STATUS_STORAGE_IO_ERROR;
00209         }
00210         if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) {
00211             return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */
00212         } else {
00213             /* synchronous completion. 'rc' contains the actual number of bytes transferred. */
00214             journal->read.offset           += rc;
00215             journal->read.amountLeftToRead -= rc;
00216             journal->read.dataBeingRead    += rc;
00217             journal->read.totalDataRead    += rc;
00218         }
00219     }
00220 
00221     journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00222     return (journal->read.dataBeingRead - journal->read.blob);
00223 }
00224 
00225 int32_t flashJournalStrategySequential_log_progress(void)
00226 {
00227     SequentialFlashJournal_t *journal = activeJournal;
00228 
00229     if ((journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE) &&
00230         (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD)  &&
00231         (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY)  &&
00232         (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL)) {
00233         return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00234     }
00235 
00236     uint32_t blobIndexBeingLogged = journal->currentBlobIndex + 1;
00237     if (blobIndexBeingLogged == SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS) {
00238         blobIndexBeingLogged = 0;
00239     }
00240 
00241     while (true) {
00242         int32_t rc;
00243 
00244         if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE) {
00245             uint64_t amountLeftToErase = journal->mtdStartOffset
00246                                          + (blobIndexBeingLogged + 1) * journal->sequentialSkip
00247                                          - journal->log.eraseOffset;
00248             // printf("journal state: erasing; offset %lu [size %lu]\n",
00249             //        (uint32_t)journal->log.eraseOffset, (uint32_t)amountLeftToErase);
00250             while (amountLeftToErase) {
00251                 if ((rc = journal->mtd->Erase(journal->log.eraseOffset, amountLeftToErase)) < ARM_DRIVER_OK) {
00252                     journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00253                     return JOURNAL_STATUS_ERROR; /* We ran out of storage blocks. Journal is in an un-expected state. */
00254                 }
00255                 if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) {
00256                     return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */
00257                 } else {
00258                     /* synchronous completion. */
00259                     journal->log.eraseOffset += rc;
00260                     amountLeftToErase        -= rc;
00261                 }
00262             }
00263         } else {
00264             ARM_STORAGE_BLOCK storageBlock;
00265 
00266             /* find the available capacity in the current storage block */
00267             while (journal->log.amountLeftToLog) {
00268                 if (journal->log.amountLeftToLog < journal->info.program_unit) {
00269                     /* We cannot log any smaller than info.program_unit. 'xfer'
00270                      * amount of data would remain unlogged. We'll break out of this loop and report
00271                      * the amount actually logged. */
00272                     break;
00273                 }
00274 
00275                 /* check for alignment of next log offset with program_unit */
00276                 if ((rc = journal->mtd->GetBlock(journal->log.offset, &storageBlock)) != ARM_DRIVER_OK) {
00277                     journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00278                     return JOURNAL_STATUS_STORAGE_API_ERROR;
00279                 }
00280                 if ((journal->log.offset - storageBlock.addr) % journal->info.program_unit) {
00281                     journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00282                     return JOURNAL_STATUS_ERROR; /* Program offset doesn't align with info.program_unit. This would result in an IO error if attempted. */
00283                 }
00284 
00285                 uint32_t xfer = journal->log.amountLeftToLog;
00286                 xfer -= xfer % journal->info.program_unit; /* align transfer-size with program_unit. */
00287 
00288                 /* perform the IO */
00289                 // printf("programming %lu bytes at offset %lu\n", xfer, (uint32_t)journal->log.offset);
00290                 rc = journal->mtd->ProgramData(journal->log.offset, journal->log.dataBeingLogged, xfer);
00291                 if (rc < ARM_DRIVER_OK) {
00292                     journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00293                     return JOURNAL_STATUS_STORAGE_IO_ERROR;
00294                 }
00295                 if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) {
00296                     return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */
00297                 } else {
00298                     /* synchronous completion. 'rc' contains the actual number of bytes transferred. */
00299                     journal->log.offset          += rc;
00300                     journal->log.amountLeftToLog -= rc;
00301                     journal->log.dataBeingLogged += rc;
00302                     if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
00303                         journal->log.tail.sizeofBlob += rc;
00304                     }
00305                 }
00306             } /* while (journal->log.amountLeftToLog) */
00307         }
00308 
00309         // printf("flashJournalStrategySequential_log_progress: state switch\n");
00310 
00311         /* state transition */
00312         switch (journal->state) {
00313             case SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE:
00314                 journal->state                   = SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD;
00315                 journal->log.offset              = journal->mtdStartOffset + blobIndexBeingLogged * journal->sequentialSkip;
00316                 journal->log.head.version        = SEQUENTIAL_FLASH_JOURNAL_VERSION;
00317                 journal->log.head.magic          = SEQUENTIAL_FLASH_JOURNAL_MAGIC;
00318                 journal->log.head.sequenceNumber = journal->nextSequenceNumber;
00319                 journal->log.head.reserved       = 0;
00320                 journal->log.dataBeingLogged     = (const uint8_t *)&journal->log.head;
00321                 journal->log.amountLeftToLog     = sizeof(SequentialFlashJournalLogHead_t);
00322                 // printf("newstate: program HEAD; amount to log %u\n", journal->log.amountLeftToLog);
00323                 break;
00324 
00325             case SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD: /* switch to writing the body */
00326                 /* Prepare for the tail to be written out at a later time.
00327                  * This will only be done once Commit() is called. */
00328                 journal->log.tailOffset          = journal->mtdStartOffset
00329                                                    + (blobIndexBeingLogged + 1) * journal->sequentialSkip
00330                                                    - sizeof(SequentialFlashJournalLogTail_t);
00331                 journal->log.tail.magic          = SEQUENTIAL_FLASH_JOURNAL_MAGIC;
00332                 journal->log.tail.sequenceNumber = journal->nextSequenceNumber;
00333                 journal->log.tail.sizeofBlob     = 0; /* we'll update this as we complete our writes. */
00334 
00335                 if (journal->prevCommand == FLASH_JOURNAL_OPCODE_COMMIT) {
00336                     /* This branch is taken only when commit() is called without any preceding log() operations. */
00337                     journal->state               = SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL;
00338                     journal->log.dataBeingLogged = (const uint8_t *)&journal->log.tail;
00339                     journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogTail_t);
00340                     journal->log.offset          = journal->log.tailOffset;
00341                     // printf("newstate: program TAIL at offset %lu\r\n", (uint32_t)journal->log.offset);
00342                 } else {
00343                     journal->state                   = SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY;
00344                     journal->log.dataBeingLogged     = journal->log.blob;
00345                     journal->log.amountLeftToLog     = journal->log.sizeofBlob;
00346                     // printf("newstate: program BODY; amount to log %u\n", journal->log.amountLeftToLog);
00347                 }
00348                 break;
00349 
00350             case SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY:
00351                 // printf("finished logging BODY; amount logged %u\n", journal->log.dataBeingLogged - journal->log.blob);
00352                 if (journal->log.dataBeingLogged == journal->log.blob) {
00353                     return JOURNAL_STATUS_SMALL_LOG_REQUEST;
00354                 } else {
00355                     return (journal->log.dataBeingLogged - journal->log.blob);
00356                 }
00357 
00358             case SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL:
00359                 journal->info.sizeofJournaledBlob = journal->log.tail.sizeofBlob;
00360                 journal->state                    = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state to allow further operations */
00361 
00362                 ++journal->currentBlobIndex;
00363                 if (journal->currentBlobIndex == SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS) {
00364                     journal->currentBlobIndex = 0;
00365                 }
00366                 // printf("currentBlobIndex: %lu\n", journal->currentBlobIndex);
00367 
00368                 /* increment next sequence number */
00369                 ++journal->nextSequenceNumber;
00370                 if (journal->nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) {
00371                     ++journal->nextSequenceNumber;
00372                 }
00373                 // printf("nextSequenceNumber %lu\n", journal->nextSequenceNumber);
00374 
00375                 return 1; /* commit returns 1 upon completion. */
00376 
00377             default:
00378                 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00379                 return JOURNAL_STATUS_ERROR;
00380         }
00381     }
00382 }
00383 
00384 void mtdHandler(int32_t status, ARM_STORAGE_OPERATION operation)
00385 {
00386     int32_t rc;
00387 
00388     if (status < ARM_DRIVER_OK) {
00389         printf("mtdHandler: received error status %" PRId32 "\n", status);
00390         switch (activeJournal->state) {
00391             case SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED:
00392             case SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS:
00393                 if (activeJournal->callback) {
00394                     activeJournal->callback(JOURNAL_STATUS_STORAGE_IO_ERROR, FLASH_JOURNAL_OPCODE_INITIALIZE);
00395                 }
00396                 break;
00397 
00398             case SEQUENTIAL_JOURNAL_STATE_RESETING:
00399                 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00400                 if (activeJournal->callback) {
00401                     activeJournal->callback(JOURNAL_STATUS_STORAGE_IO_ERROR, FLASH_JOURNAL_OPCODE_RESET);
00402                 }
00403                 break;
00404 
00405             case SEQUENTIAL_JOURNAL_STATE_INITIALIZED:
00406             case SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE:
00407             case SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD:
00408             case SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY:
00409             case SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL:
00410                 /* reset journal state to allow further operation. */
00411                 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00412 
00413                 if (activeJournal->callback) {
00414                     activeJournal->callback(JOURNAL_STATUS_STORAGE_IO_ERROR, FLASH_JOURNAL_OPCODE_LOG_BLOB);
00415                 }
00416                 break;
00417             case SEQUENTIAL_JOURNAL_STATE_READING:
00418                 /* reset journal state to allow further operation. */
00419                 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00420 
00421                 if (activeJournal->callback) {
00422                     activeJournal->callback(JOURNAL_STATUS_STORAGE_IO_ERROR, FLASH_JOURNAL_OPCODE_READ_BLOB);
00423                 }
00424                 break;
00425         }
00426 
00427         return;
00428     }
00429 
00430     switch (operation) {
00431         case ARM_STORAGE_OPERATION_INITIALIZE:
00432             if (activeJournal->callback) {
00433                 activeJournal->callback(JOURNAL_STATUS_OK, FLASH_JOURNAL_OPCODE_INITIALIZE);
00434             }
00435             break;
00436 
00437         case ARM_STORAGE_OPERATION_ERASE_ALL:
00438             if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_RESETING) {
00439                 activeJournal->nextSequenceNumber       = 0;
00440                 activeJournal->currentBlobIndex         = (uint32_t)-1;
00441                 activeJournal->info.sizeofJournaledBlob = 0;
00442                 activeJournal->state                    = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00443                 if (activeJournal->callback) {
00444                     activeJournal->callback(JOURNAL_STATUS_OK, FLASH_JOURNAL_OPCODE_RESET);
00445                 }
00446             }
00447             break;
00448 
00449         case ARM_STORAGE_OPERATION_ERASE:
00450             if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE) {
00451                 if (status <= ARM_DRIVER_OK) {
00452                     if (activeJournal->callback) {
00453                         activeJournal->callback(JOURNAL_STATUS_STORAGE_API_ERROR, FLASH_JOURNAL_OPCODE_LOG_BLOB);
00454                     }
00455                     return;
00456                 }
00457 
00458                 activeJournal->log.eraseOffset += status;
00459 
00460                 if ((rc = flashJournalStrategySequential_log_progress()) != JOURNAL_STATUS_OK) {
00461                     activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00462                     if (activeJournal->callback) {
00463                         activeJournal->callback(rc, FLASH_JOURNAL_OPCODE_LOG_BLOB);
00464                     }
00465                     return;
00466                 }
00467             } else if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_RESETING) {
00468                 activeJournal->nextSequenceNumber       = 0;
00469                 activeJournal->currentBlobIndex         = (uint32_t)-1;
00470                 activeJournal->info.sizeofJournaledBlob = 0;
00471                 activeJournal->state                    = SEQUENTIAL_JOURNAL_STATE_INITIALIZED;
00472                 if (activeJournal->callback) {
00473                     activeJournal->callback(JOURNAL_STATUS_OK, FLASH_JOURNAL_OPCODE_RESET);
00474                 }
00475             }
00476             break;
00477 
00478         case ARM_STORAGE_OPERATION_PROGRAM_DATA:
00479             // printf("PROGRAM_DATA: received status of %ld\n", status);
00480             rc = status;
00481             activeJournal->log.offset          += rc;
00482             activeJournal->log.amountLeftToLog -= rc;
00483             activeJournal->log.dataBeingLogged += rc;
00484             if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
00485                 activeJournal->log.tail.sizeofBlob += rc;
00486             }
00487 
00488             if ((rc = flashJournalStrategySequential_log_progress()) < JOURNAL_STATUS_OK) {
00489                 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */
00490                 if (activeJournal->callback) {
00491                     activeJournal->callback(rc,
00492                                             (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL) ?
00493                                                 FLASH_JOURNAL_OPCODE_COMMIT : FLASH_JOURNAL_OPCODE_LOG_BLOB);
00494                 }
00495                 return;
00496             }
00497             if ((rc == JOURNAL_STATUS_OK) && (activeJournal->log.amountLeftToLog > 0)) {
00498                 return; /* we've got pending asynchronous activity */
00499             }
00500             if (activeJournal->callback) {
00501                 activeJournal->callback(rc, (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_INITIALIZED) ?
00502                                                 FLASH_JOURNAL_OPCODE_COMMIT : FLASH_JOURNAL_OPCODE_LOG_BLOB);
00503             }
00504             break;
00505 
00506         default:
00507             printf("mtdHandler: unknown operation %u\n", operation);
00508             break;
00509     }
00510 }