Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
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 }
Generated on Fri Jul 22 2022 04:54:01 by
 1.7.2
 1.7.2 
    