Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage_volume_manager.cpp Source File

storage_volume_manager.cpp

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 // This file is deprecated so deprecation warnings when building it are silenced
00019 #if   defined ( __CC_ARM )
00020 #pragma diag_suppress 1361  // Deprecated declaration
00021 #elif defined ( __GNUC__ )
00022 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
00023 #endif
00024 
00025 #include "storage-volume-manager/storage_volume_manager.h"
00026 #include <string.h>
00027 #include <inttypes.h>
00028 
00029 /* redefine these macros to a printf() equivalent to emit trace */
00030 #define tr_debug(...)
00031 #define tr_error(...)
00032 
00033 /*
00034  * The following variable records the volume-manager instance which last setup
00035  * StorageVolumeManager::storageCallback() as a callback for a storage driver.
00036  * We use this value in the callback handler to de-multiplex the callback into a
00037  * volume-manager.
00038  */
00039 static StorageVolumeManager *activeVolumeManager;
00040 
00041 InitializeCallback_t initializeCallback;
00042 
00043 #define STORAGE_API_DEFINITIONS_FOR_VOLUME(N)                                          \
00044 extern "C" ARM_DRIVER_VERSION GetVersion_ ## N(void) {                                 \
00045     return activeVolumeManager->volumes[(N)].GetVersion();                             \
00046 }                                                                                      \
00047 ARM_STORAGE_CAPABILITIES GetCapabilities_ ## N(void) {                                 \
00048     return activeVolumeManager->volumes[(N)].GetCapabilities();                        \
00049 }                                                                                      \
00050 int32_t Initialize_ ## N(ARM_Storage_Callback_t callback) {                            \
00051     return activeVolumeManager->volumes[(N)].Initialize(callback);                     \
00052 }                                                                                      \
00053 int32_t Uninitialize_ ## N(void) {                                                     \
00054     return activeVolumeManager->volumes[(N)].Uninitialize();                           \
00055 }                                                                                      \
00056 int32_t PowerControl_ ## N(ARM_POWER_STATE state) {                                    \
00057     return activeVolumeManager->volumes[(N)].PowerControl(state);                      \
00058 }                                                                                      \
00059 int32_t ReadData_ ## N(uint64_t addr, void *data, uint32_t size) {                     \
00060     return activeVolumeManager->volumes[(N)].ReadData(addr, data, size);               \
00061 }                                                                                      \
00062 int32_t ProgramData_ ## N(uint64_t addr, const void *data, uint32_t size) {            \
00063     return activeVolumeManager->volumes[(N)].ProgramData(addr, data, size);            \
00064 }                                                                                      \
00065 int32_t Erase_ ## N(uint64_t addr, uint32_t size) {                                    \
00066     return activeVolumeManager->volumes[(N)].Erase(addr, size);                        \
00067 }                                                                                      \
00068 int32_t EraseAll_ ## N(void) {                                                         \
00069     return activeVolumeManager->volumes[(N)].EraseAll();                               \
00070 }                                                                                      \
00071 ARM_STORAGE_STATUS GetStatus_ ## N(void) {                                             \
00072     return activeVolumeManager->volumes[(N)].GetStatus();                              \
00073 }                                                                                      \
00074 int32_t GetInfo_ ## N(ARM_STORAGE_INFO *infoP) {                                       \
00075     return activeVolumeManager->volumes[(N)].GetInfo(infoP);                           \
00076 }                                                                                      \
00077 uint32_t ResolveAddress_ ## N(uint64_t addr) {                                         \
00078     return activeVolumeManager->volumes[(N)].ResolveAddress(addr);                     \
00079 }                                                                                      \
00080 int32_t GetNextBlock_ ## N(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP) { \
00081     return activeVolumeManager->volumes[(N)].GetNextBlock(prevP, nextP);               \
00082 }                                                                                      \
00083 int32_t GetBlock_ ## N(uint64_t addr, ARM_STORAGE_BLOCK *blockP) {                     \
00084     return activeVolumeManager->volumes[(N)].GetBlock(addr, blockP);                   \
00085 }                                                                                      \
00086 ARM_DRIVER_STORAGE VIRTUAL_MTD_ ## N = {                                               \
00087     .GetVersion      = GetVersion_ ## N,                                               \
00088     .GetCapabilities = GetCapabilities_ ## N,                                          \
00089     .Initialize      = Initialize_ ## N,                                               \
00090     .Uninitialize    = Uninitialize_ ## N,                                             \
00091     .PowerControl    = PowerControl_ ## N,                                             \
00092     .ReadData        = ReadData_ ## N,                                                 \
00093     .ProgramData     = ProgramData_ ## N,                                              \
00094     .Erase           = Erase_ ## N,                                                    \
00095     .EraseAll        = EraseAll_ ## N,                                                 \
00096     .GetStatus       = GetStatus_ ## N,                                                \
00097     .GetInfo         = GetInfo_ ## N,                                                  \
00098     .ResolveAddress  = ResolveAddress_ ## N,                                           \
00099     .GetNextBlock    = GetNextBlock_ ## N,                                             \
00100     .GetBlock        = GetBlock_ ## N,                                                 \
00101 };
00102 
00103 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_1 STORAGE_API_DEFINITIONS_FOR_VOLUME(0)
00104 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_2 STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_1 STORAGE_API_DEFINITIONS_FOR_VOLUME(1)
00105 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_3 STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_2 STORAGE_API_DEFINITIONS_FOR_VOLUME(2)
00106 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_4 STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_3 STORAGE_API_DEFINITIONS_FOR_VOLUME(3)
00107 /* ... add more of the above if ever needed */
00108 
00109 #define STORAGE_API_DEFINITIONS_FOR_VOLUMES(N) EXPAND(CONCATENATE(STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_, N))
00110 
00111 STORAGE_API_DEFINITIONS_FOR_VOLUMES(MAX_VOLUMES);
00112 
00113 int32_t StorageVolumeManager::initialize(ARM_DRIVER_STORAGE *mtd, InitializeCallback_t callback)
00114 {
00115     activeVolume        = NULL;
00116     initializeCallback  = callback;
00117 
00118     storage             = mtd;
00119     storageCapabilities = mtd->GetCapabilities();
00120 
00121     int32_t rc = mtd->GetInfo(&storageInfo);
00122     if (rc != ARM_DRIVER_OK) {
00123         tr_error("StorageVolumeManager::initialize: call to GetInfo() failed with %" PRId32, rc);
00124         return ARM_DRIVER_ERROR;
00125     }
00126 
00127     rc = mtd->Initialize(storageCallback);
00128     if (rc < ARM_DRIVER_OK) {
00129         tr_error("Initialize() failed with error %" PRId32, rc);
00130         return ARM_DRIVER_ERROR;
00131     }
00132 
00133     activeVolumeManager = this;
00134     if (rc == ARM_DRIVER_OK) {
00135         /* there is pending asynchronous activity which will result in a callback later */
00136         return ARM_DRIVER_OK;
00137     }
00138 
00139     /* Clear previously allocated volumes */
00140     for (size_t i = 0; i < MAX_VOLUMES; i++) {
00141         if (volumes[i].isAllocated()) {
00142             volumes[i].deallocate();
00143         }
00144     }
00145 
00146     /* synchronous completion */
00147     initialized = true;
00148     return 1;
00149 }
00150 
00151 int32_t StorageVolumeManager::addVolume(uint64_t addr, uint64_t size, StorageVolume **volumePP)
00152 {
00153     tr_debug("StorageVolumeManager_addVolume: addr = %" PRIu32 ", size = %" PRIu32, (uint32_t)addr, (uint32_t)size);
00154 
00155     *volumePP = NULL;
00156 
00157     /*
00158      * sanity checks for arguments
00159      */
00160     ARM_STORAGE_INFO info;
00161     int32_t rc;
00162     rc = storage->GetInfo(&info);
00163     if (rc != ARM_DRIVER_OK) {
00164         tr_error("StorageVolumeManager_addVolume: storage->GetInfo() failed with %" PRId32, rc);
00165         return ARM_DRIVER_ERROR;
00166     }
00167     if (size > info.total_storage) {
00168         tr_error("StorageVolumeManager_addVolume: 'size' parameter too large: %" PRIu32, (uint32_t)size);
00169         return ARM_DRIVER_ERROR;
00170     }
00171     ARM_STORAGE_BLOCK firstBlock;
00172     rc = storage->GetNextBlock(NULL, &firstBlock);
00173     if (rc != ARM_DRIVER_OK) {
00174         tr_error("StorageVolumeManager_addVolume: storage->GetNextBlock() failed with %" PRId32, rc);
00175         return ARM_DRIVER_ERROR;
00176     }
00177     if ((addr < firstBlock.addr) || ((addr + size) > (firstBlock.addr + info.total_storage))) {
00178         tr_error("StorageVolumeManager_addVolume: given range [%" PRIu32 ", %" PRIu32 ") isn't entirely contained within available storage range [%" PRIu32 ", %" PRIu32 ")",
00179             (uint32_t)addr, (uint32_t)(addr + size), (uint32_t)firstBlock.addr, (uint32_t)(firstBlock.addr + info.total_storage));
00180         return ARM_DRIVER_ERROR;
00181     }
00182 
00183     /* Find an unused volume. */
00184     uint32_t index = findIndexOfUnusedVolume();
00185     if (index == MAX_VOLUMES) {
00186         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_EXHASTED_VOLUMES;
00187     }
00188 
00189     /* setup volume */
00190     StorageVolume *volumeP = &volumes[index];
00191     volumeP->setup(addr, size, this);
00192     *volumePP = volumeP;
00193     tr_debug("StorageVolumeManager_addVolume: setup volume at index %" PRIu32, index);
00194 
00195     return ARM_DRIVER_OK;
00196 }
00197 
00198 int32_t StorageVolumeManager::addVolume_C(uint64_t addr, uint64_t size, _ARM_DRIVER_STORAGE *mtd)
00199 {
00200     int32_t rc;
00201     StorageVolume *volumeP;
00202     if ((rc = addVolume(addr, size, &volumeP)) < ARM_DRIVER_OK) {
00203         return rc;
00204     }
00205 
00206     /* locate index of the allocated volume */
00207     size_t index;
00208     for (index = 0; index < MAX_VOLUMES; index++) {
00209         if (volumes[index].isAllocated() && (&volumes[index] == volumeP)) {
00210             break;
00211         }
00212     }
00213     if (index == MAX_VOLUMES) {
00214         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_EXHASTED_VOLUMES;
00215     }
00216 
00217     if (index == 0) {
00218         *mtd = VIRTUAL_MTD_0;
00219     } else if (index == 1) {
00220         *mtd = VIRTUAL_MTD_1;
00221     } else if (index == 2) {
00222         *mtd = VIRTUAL_MTD_2;
00223     } else if (index == 3) {
00224         *mtd = VIRTUAL_MTD_3;
00225     } else {
00226         return ARM_DRIVER_ERROR;
00227     }
00228 
00229     return ARM_DRIVER_OK;
00230 }
00231 
00232 int32_t StorageVolumeManager::lookupVolume(uint64_t addr, StorageVolume **volumePP)
00233 {
00234     /*
00235      * Traverse the volumes in reverse order of creation; this allows newly created volumes to supersede the older ones.
00236      */
00237     for (size_t index = MAX_VOLUMES - 1; index > 0; --index) {
00238         StorageVolume *volume = &volumes[index];
00239         if ((addr >= volume->getVolumeOffset()) && (addr < (volume->getVolumeOffset() + volume->getVolumeSize()))) {
00240             *volumePP = volume;
00241             return ARM_DRIVER_OK;
00242         }
00243     }
00244 
00245     return ARM_DRIVER_ERROR;
00246 }
00247 
00248 void StorageVolumeManager::storageCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00249 {
00250     tr_debug("StorageVolumeManager_callback: operation = %u", operation);
00251     StorageVolumeManager *volumeManager = activeVolumeManager;
00252 
00253     switch (operation) {
00254         case ARM_STORAGE_OPERATION_INITIALIZE:
00255             volumeManager->initialized = true;
00256             if (initializeCallback != NULL) {
00257                 initializeCallback(status);
00258             }
00259             break;
00260 
00261         case ARM_STORAGE_OPERATION_POWER_CONTROL:
00262         case ARM_STORAGE_OPERATION_READ_DATA:
00263         case ARM_STORAGE_OPERATION_PROGRAM_DATA:
00264         case ARM_STORAGE_OPERATION_ERASE:
00265         case ARM_STORAGE_OPERATION_ERASE_ALL:
00266             if (volumeManager->activeVolume != NULL) {
00267                 /* Reset activeVolume and invoke callback. We reset activeVolume before the
00268                  * callback because the callback may attempt to launch another asynchronous
00269                  * operation, which requires 'activeVolume' to be NULL. */
00270                 StorageVolume *callbackVolume = volumeManager->activeVolume; /* remember the volume which will receive the callback. */
00271                 volumeManager->activeVolume   = NULL;
00272 
00273                 if (callbackVolume->isAllocated() && callbackVolume->getCallback()) {
00274                     (callbackVolume->getCallback())(status, operation);
00275                 }
00276             }
00277             break;
00278 
00279         default:
00280             tr_error("StorageVolumeManager_callback: unknown operation %u", operation);
00281             break;
00282     }
00283 }
00284 
00285 size_t StorageVolumeManager::findIndexOfUnusedVolume(void) const {
00286     size_t index;
00287     for (index = 0; index < MAX_VOLUMES; index++) {
00288         if (!volumes[index].isAllocated()) {
00289             break;
00290         }
00291     }
00292     return index;
00293 }