]> rtime.felk.cvut.cz Git - arc.git/blob - memory/NvM/NvM.c
Mixed bug fixing..
[arc.git] / memory / NvM / NvM.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 /*\r
17  * RamBlockDataAddress\r
18  *   NULL is no permanent RAM block. Otherwise allocate the number of bytes in space (like the stack)\r
19  *\r
20  *\r
21  * Understanding block numbering:\r
22  *\r
23  *  NVM_DATASET_SELECTION_BIT=2\r
24  *\r
25  *    NvBlockBaseNumber\r
26  *          0     Reserved (NVM478)\r
27  *          1     NVM_BLOCK_NATIVE,    NvBlockNum=1\r
28  *          2     NVM_BLOCK_REDUNDANT, NvBlockNum=2\r
29  *          3     NVM_BLOCK_DATASET,   NvBlockNum=4\r
30  *\r
31  *   NvM_ReadBlock( 0, ... )    - Reserved for "multi block requests"\r
32  *   NvM_ReadBlock( 1, ... )    - Reserved for redundant NVRAM block which holds the configuration ID.\r
33  *   NvM_ReadBlock( 2--x, ... ) - "Normal" blocks\r
34  *\r
35  *\r
36  *  NvM_BlockIdType*)  NvBlockBaseNumber   EA_BLOCK_NUMBER\r
37  *      0**)\r
38  *      1**)                ***)\r
39  *      2                   1                           4, (5,6,7)  ****)\r
40  *      3                   2                           8, R9,(10,11)  ****)\r
41  *      4                   3                           12, D13,D14,D15 ****)\r
42  *\r
43  *  *) Type used in the API.\r
44  *  **)   Reserved ID's\r
45  *  ***)  Reserved ID\r
46  *  ****) FEE/EA_BLOCK_NUMBER = NvBlockBaseNumber << NvmDatasetSelectionBits = NvBlockBaseNumber * 4\r
47  *        () - Cannot be accesses due to NvBlockNum\r
48  *        R9 - Redundant block\r
49  *        Dx - Data blocks\r
50  *\r
51  *    SIZES\r
52  *      Both NvM and EA/FEE have block sizes. NvM have NvNvmBlockLength (NVM479) and FEE/EA have EaBlockSize.\r
53  *      FEE/EA also have virtual page that is the alignment of a block, with the smallest block=size of the virtual page.\r
54  *\r
55  *      So, who allocates space for this. FEE/EA only have EaBlockSize.\r
56  *      NvM have NvmRamBlockDataAddress, NvmRomBlockDataAddress and mapping to a MemIf Blocks (FEE/EA blocks)\r
57  *\r
58  *      ASSUME: I can't really see a point for the FEE/EA EaBlockSize.. it will just a multiple of NvNvmBlockLength*NvBlockNum + overhead?\r
59  *              Click-box in EA/FEE that leaves the size calculation to NvM?\r
60  *              This also means that enabling NvmBlockUseCrc or set a block from NVM_BLOCK_NATIVE to NVM_BLOCK_DATASET would be "automatic"\r
61  *              in calculation of the EaBlockSize.\r
62  *\r
63  *      So how much data should be read from MemIf if a CRC checksum is used. Assuming that we use a physical layout where the CRC is located\r
64  *      after the NV Block it would be BALIGN(NvNvmBlockLength,4) + 4 bytes. The same applies to the RAM block (ROM block to not have CRC, NVM127)\r
65  *\r
66  * CRC\r
67  *   NVM121: NvM_SetRamBlockStatus(), calculate CRC in background if NvmCalcRamBlockCrc==TRUE\r
68  *   NVM362: NvM_ReadAll() , if (NvmCalcRamBlockCrc == TRUE && permanent RAM block) re-calc CRC.\r
69  *\r
70  *     NvmBlockUseCrc     - Global CRC switch. Space is allocated in both RAM and NV block\r
71  *     NvmCalcRamBlockCrc - CRC re-calculation. For example during startup, you may don't want\r
72  *                          to verify all the checksums again, but instead just copy from NV\r
73  *                          to RAM.\r
74  *\r
75  *     There is also explicit RAM checksum calculations for example NVM253 (Nvm_WriteAll()) where a CRC calculation\r
76  *     is requested (although not stated should be dependent on NvmBlockUseCrc only, not NvmCalcRamBlockCrc).\r
77  *     You have to calculate the checksum at some point....\r
78  *\r
79  * QUEUES\r
80  *   NVM185: Says "successful enqueueing a request".."set to NVM_REQ_PENDING"\r
81  *   NVM380: The queue length for multi block request shall be one (NvM_ReadAll, NvM_WriteAll)\r
82  *   NVM381+NVM567 : Multi block requests shall not be interrupted.\r
83  *   NVM243+NVM245: Do not unqueue the multi block request until all single block queues are empty.\r
84  *     So, when NvmState==IDLE and we have a multi-request\r
85  *\r
86  *\r
87  *\r
88  *\r
89  *\r
90  * SPEED\r
91  *   To get some speed into this multiple thing must be done in the same MainFunction loop.\r
92  *\r
93  * MEMIF\r
94  *   The interface is actually quite strange, so you may read from any address (through MemIf_Read())\r
95  *   but MemIf_Write(..) only takes a logical block and a pointer to the data to write.\r
96  *\r
97  *   See two alternatives here:\r
98  *    1. If the NVBlock also contains the checksum after the data then writing the data needs a\r
99  *       RAM that is as big as the biggest RAM block + room for checksum.\r
100  *    2. If checksums would be kept in a separate EA/FEE block the ALL the checksum need to be written.\r
101  *       For example after a NvM_WriteBlock() the checksum block would need to be written. This\r
102  *       will probably lead consistency problems also... what happens if we fail to write the checksum\r
103  *       block?\r
104  *\r
105  *\r
106  *\r
107  * MANUAL\r
108  *\r
109  *\r
110  *\r
111  *   Provide Data for the first/initial read\r
112  *     When a block have no\r
113  *\r
114  *     NVM085\r
115  *     NVM061\r
116  *     NVM083\r
117  *\r
118  *   Configuring CRCs\r
119  *     BlockUseCrc (A):      If the block (both RAM and NV) should use CRC\r
120  *     CalcRamBlockCrc (B):  If the permanent RAM block should re-calculate it's CRC.\r
121  *\r
122  *     A B\r
123  *     ------------\r
124  *     0 0  No error detection or recovery\r
125  *     0 1  N/A\r
126  *     1 0  ?\r
127  *     1 1  ?\r
128  *\r
129  * RAM BLOCK VALID/UNCHANGED\r
130  *   Figure 8 and 9 in 3.1.5/NVM is more confusing than good.\r
131  *   What we have to know is:\r
132  *    1. Initially the RAM block is in INVALID/UNCHANGED\r
133  *    ALT 2. After a NvM_ReadAll() and all is well the state goes to VALID/UNCHANGED\r
134  *    ALT 2. If ROM values are used we go to VALID/CHANGED (We failed to read from NVRAM)\r
135  *\r
136  *   For NvM_WriteAll()\r
137  *   1. A block that is INVALID can't be written\r
138  *   2. A block that is UNCHANGED should not be written.\r
139  *   -> Write only blocks that are VALID/CHANGED.\r
140  *\r
141  *   VALID/UNCHANGED - RAM == NV\r
142  *   VALID/CHANGED   - RAM != NV   (analog to cache memories, "dirty")\r
143  *\r
144  *   Analog to cache\r
145  *     VALID/CHANGED state - Dirty (since RAM != NV)\r
146  *     WriteBlock          - Flush (Flush the RAM block to NV)\r
147  *     ReadBlock           - Invalidate (NV block is read to RAM)\r
148  */\r
149 \r
150 \r
151 /*\r
152  *  General requirements\r
153  */\r
154 /** @req NVM076 */\r
155 /** @req NVM552 */\r
156 /** @req NVM689 */\r
157 \r
158 \r
159 /*\r
160  * NB! Even though some code exist for handling RamCrc, the functionality is not complete\r
161  * and shall not be used.
162  */\r
163 \r
164 //lint -esym(522,CalcCrc) // 522 PC-Lint exception for empty functions\r
165 //lint -emacro(904,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
166 \r
167 // Exception made as a result of that NVM_DATASET_SELECTION_BITS can be zero\r
168 //lint -emacro(835, BLOCK_BASE_AND_SET_TO_BLOCKNR) // 835 PC-lint: A zero has been given as right argument to operator '<<' or '>>'\r
169 \r
170 \r
171 /* ----------------------------[includes]------------------------------------*/\r
172 \r
173 #include <assert.h>\r
174 #include "NvM.h"\r
175 #include "NvM_Cbk.h"\r
176 #include "Rte.h" // ???\r
177 #if defined(USE_DEM)\r
178 #include "Dem.h"\r
179 #endif\r
180 #include "MemIf.h"\r
181 //#include "SchM_NvM.h"\r
182 #include "MemMap.h"\r
183 #include "cirq_buffer.h"\r
184 #include "Modules.h"\r
185 #include <stdio.h>\r
186 #include "io.h"\r
187 #include "Crc.h"\r
188 #include <string.h>\r
189 \r
190 #define FIXME           0\r
191 \r
192 //#define DEBUG_BLOCK   1\r
193 #if defined(DEBUG_BLOCK)\r
194 #define DEBUG_BLOCK_STATE(_str,_block,_state)       printf("%s BLOCK NR:%d STATE:%d\n",_str,_block, _state); fflush(stdout);\r
195 #define DEBUG_STATE(_state,_substate)                           printf("MAIN_STATE:%s/%d\n",StateToStr[_state],_substate); fflush(stdout);\r
196 #define DEBUG_PRINTF(format,...)                                        printf(format,## __VA_ARGS__ ); fflush(stdout);\r
197 #define DEBUG_CHECKSUM(_str,_crc)                                       printf("%s crc=%x\n",_str,_crc);\r
198 #else\r
199 #define DEBUG_BLOCK_STATE(_str,_block,_state)\r
200 #define DEBUG_STATE(_state,_substate)\r
201 #define DEBUG_PRINTF(format,...)\r
202 #define DEBUG_CHECKSUM(_str,_crc)\r
203 #endif\r
204 \r
205 \r
206 /* ----------------------------[private define]------------------------------*/\r
207 \r
208 \r
209 \r
210 #define NVM_BLOCK_ALIGNMENT                     4\r
211 #define NVM_CHECKSUM_LENGTH                     4\r
212 \r
213 #define NVM_BLOCK_OFFSET                2\r
214 \r
215 \r
216 \r
217 \r
218 \r
219 /* ----------------------------[private macro]-------------------------------*/\r
220 \r
221 #define NVM_ASSERT(_exp)                if( !(_exp) ) { while(1) {}; } //assert(_exp)\r
222 \r
223 #if  ( NVM_DEV_ERROR_DETECT == STD_ON )\r
224 #include "Det.h"\r
225 #define VALIDATE(_exp,_api,_err ) \\r
226         if( !(_exp) ) { \\r
227           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
228         }\r
229 \r
230 \r
231 #define VALIDATE_RV(_exp,_api,_err,_rv ) \\r
232         if( !(_exp) ) { \\r
233           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
234           return _rv; \\r
235         }\r
236 \r
237 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
238         if( !(_exp) ) { \\r
239           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
240           return; \\r
241         }\r
242 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)\r
243 \r
244 #else\r
245 #define VALIDATE(_exp,_api,_err )\r
246 #define VALIDATE_RV(_exp,_api,_err,_rv )\r
247 #define VALIDATE_NO_RV(_exp,_api,_err )\r
248 #define DET_REPORTERROR(_module,_instance,_api,_err)\r
249 #endif\r
250 \r
251 #define BLOCK_BASE_AND_SET_TO_BLOCKNR(_blockbase, _set) ((uint16)(_blockbase << NVM_DATASET_SELECTION_BITS) | _set)\r
252 \r
253 #if defined(USE_DEM)\r
254 #define DEM_REPORTERRORSTATUS(_err,_ev ) Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED);\r
255 #else\r
256 #define DEM_REPORTERRORSTATUS(_err,_ev )\r
257 #endif\r
258 \r
259 \r
260 #define BLOCK_NR_FROM_PTR(_bptr)                (((_bptr) - NvM_Config.BlockDescriptor + 1))   // sizeof(NvM_BlockDescriptorType))\r
261 \r
262 #define CREATE_ENTRY(_val)      [_val] = #_val\r
263 \r
264 \r
265 \r
266 \r
267 /* ----------------------------[private typedef]-----------------------------*/\r
268 \r
269 // State variable\r
270 typedef enum {\r
271   NVM_UNINITIALIZED = 0,\r
272   NVM_IDLE,\r
273   NVM_READ_ALL,\r
274   NVM_WRITE_ALL,\r
275   NVM_READ_BLOCK,\r
276   NVM_WRITE_BLOCK,\r
277   NVM_RESTORE_BLOCK_DEFAULTS,\r
278 } NvmStateType;\r
279 \r
280 char *StateToStr[20] = {\r
281         CREATE_ENTRY(NVM_UNINITIALIZED),\r
282         CREATE_ENTRY(NVM_IDLE),\r
283         CREATE_ENTRY(NVM_READ_ALL),\r
284         CREATE_ENTRY(NVM_WRITE_ALL),\r
285         CREATE_ENTRY(NVM_READ_BLOCK),\r
286         CREATE_ENTRY(NVM_WRITE_BLOCK),\r
287  };\r
288 \r
289 \r
290 typedef enum {\r
291         BLOCK_STATE_MEMIF_REQ,\r
292 //      BLOCK_STATE_START,\r
293         BLOCK_STATE_MEMIF_PROCESS,\r
294 //      BLOCK_STATE_MEMIF_CRC_PROCESS,\r
295         BLOCK_STATE_CALC_CRC,\r
296 //      BLOCK_STATE_MEMIF_PROCESS_CRC,\r
297         BLOCK_STATE_CALC_CRC_WRITE,\r
298         BLOCK_STATE_CALC_CRC_READ,\r
299 //      BLOCK_STATE_LOAD_FROM_NV,\r
300 } BlockStateType;\r
301 \r
302 typedef enum {\r
303         NS_INIT = 0,\r
304         NS_PROSSING,\r
305 //      RB_PROCESSING,\r
306 } Nvm_SubStates;\r
307 \r
308 \r
309 union Nvm_CRC {\r
310         uint16 crc16;\r
311         uint32 crc32;\r
312 };\r
313 \r
314 \r
315 typedef struct {\r
316         NvM_RequestResultType   ErrorStatus;                    // Status from multi block requests i.e. Read/Write/CancelWrite-all\r
317 } AdministrativeMultiBlockType;\r
318 \r
319 typedef struct {\r
320         BlockStateType                  BlockState;\r
321         uint8                                   DataIndex;                              // Selected data index if "Data Set" type\r
322         boolean                                 BlockWriteProtected;    // Block write protected?\r
323         NvM_RequestResultType   ErrorStatus;                    // Status of block\r
324         boolean                                 BlockChanged;                   // Block changed?\r
325         boolean                                 BlockValid;                             // Block valid? (RAM block only?)\r
326         uint8                                   NumberOfWriteFailed;    // Current write retry cycle\r
327         union Nvm_CRC                   RamCrc;\r
328         union Nvm_CRC                   NvCrc;                                  // The CRC of this block, read from NV\r
329         void *                                  savedDataPtr;                   //\r
330         uint8                                   crcLen;\r
331 \r
332 } AdministrativeBlockType;\r
333 \r
334 /*\r
335 typedef enum {\r
336         NVM_OP_READ_BLOCK,\r
337         NVM_OP_WRITE_BLOCK,\r
338         NVM_OP_RESTORE_BLOCK_DEFAULTS,\r
339 } Nvm_OpType;\r
340 */\r
341 #define OP_READ         0\r
342 #define OP_WRITE        1\r
343 #define NO_MULTIBLOCK   0\r
344 #define MULTIBLOCK              1\r
345 \r
346 \r
347 typedef struct {\r
348         NvmStateType            op;\r
349         NvM_BlockIdType blockId;\r
350         uint8 *                 dataPtr;        /* Src or Dest ptr */\r
351 } Nvm_QueueType;\r
352 \r
353 \r
354 \r
355 /* ----------------------------[private function prototypes]-----------------*/\r
356 /* ----------------------------[private variables]---------------------------*/\r
357 \r
358 static NvmStateType                             nvmState = NVM_UNINITIALIZED;\r
359 \r
360 #define RB_START                        0\r
361 #define RB_WAIT_READ            1\r
362 #define RB_CALC_CHECKSUM        2\r
363 \r
364 static int                                                      nvmSubState = 0;\r
365 //static int nvmSetNr;\r
366 static AdministrativeBlockType          AdminBlock[NVM_NUM_OF_NVRAM_BLOCKS];\r
367 static AdministrativeMultiBlockType AdminMultiBlock;\r
368 \r
369 \r
370 //static Nvm_QueueType  nvmQueueImmData[NVM_SIZE_IMMEDIATE_JOB_QUEUE];\r
371 static Nvm_QueueType  nvmQueueData[NVM_SIZE_STANDARD_JOB_QUEUE];\r
372 \r
373 uint8 Nvm_WorkBuffer[200];              /* TODO */\r
374 \r
375 #if (NVM_SIZE_STANDARD_JOB_QUEUE == 0)\r
376 #error NVM_SIZE_STANDARD_JOB_QUEUE have size 0\r
377 #endif\r
378 \r
379 \r
380 CirqBufferType nvmQueue;\r
381 \r
382 \r
383 /* ----------------------------[private functions]---------------------------*/\r
384 \r
385 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,\r
386                                                 AdministrativeBlockType *adminBlock,\r
387                                                 uint8 setNumber,\r
388                                                 uint8 *sourceAddress);\r
389 \r
390 /* ----------------------------[public functions]----------------------------*/\r
391 \r
392 \r
393 \r
394 /*\r
395  * This function needs to be implemented!
396  */\r
397 static void CalcCrc(void)\r
398 {\r
399         // TODO: Calculate CRC\r
400 }\r
401 \r
402 typedef struct {\r
403         boolean                                                 JobFinished;\r
404         Std_ReturnType                                  JobStatus;\r
405         MemIf_JobResultType                     JobResult;\r
406         const NvM_BlockDescriptorType * BlockDescriptor;\r
407         AdministrativeBlockType *               BlockAdmin;\r
408 } MemIfJobAdminType;\r
409 \r
410 static MemIfJobAdminType MemIfJobAdmin = {\r
411                 .JobFinished = TRUE,\r
412                 .JobStatus = E_OK,\r
413                 .JobResult = MEMIF_JOB_OK,\r
414                 .BlockDescriptor = NULL,\r
415                 .BlockAdmin = NULL\r
416 };\r
417 \r
418 enum Nvm_MultiBlockReq {\r
419         MB_REQ_NONE,\r
420         MB_REQ_READ_ALL,\r
421         MB_REQ_WRITE_ALL,\r
422 };\r
423 \r
424 typedef struct {\r
425         NvmStateType                    state;\r
426         uint16                                  currBlockIndex;         // Keeps track of next unfinished block\r
427         NvM_RequestResultType   PendingErrorStatus;     // Status from multi block requests i.e. Read/Write/CancelWrite-all\r
428 } AdminMultiReqType;\r
429 \r
430 static AdminMultiReqType AdminMultiReq;\r
431 \r
432 \r
433 /*\r
434  * Set the MemIf job as busy
435  */\r
436 static void SetMemifJobBusy()\r
437 {\r
438         MemIfJobAdmin.JobFinished = FALSE;\r
439 }\r
440 \r
441 \r
442 #if (NVM_POLLING_MODE == STD_ON)\r
443 /*\r
444  * Check if the MemIf job is finished
445  */\r
446 static boolean CheckMemIfJobFinished(void)\r
447 {\r
448         MemIf_JobResultType jobResult;\r
449 \r
450         if (!MemIfJobAdmin.JobFinished) {\r
451                 jobResult = MemIf_GetJobResult(FIXME);\r
452 \r
453                 if (jobResult == MEMIF_JOB_OK) {\r
454                         MemIfJobAdmin.JobFinished = TRUE;\r
455                         MemIfJobAdmin.JobStatus = E_OK;\r
456                         MemIfJobAdmin.JobResult = jobResult;\r
457                 } else if (jobResult != MEMIF_JOB_PENDING) {\r
458                         MemIfJobAdmin.JobFinished = TRUE;\r
459                         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
460                         MemIfJobAdmin.JobResult = jobResult;\r
461                 }\r
462         }\r
463 \r
464         return MemIfJobAdmin.JobFinished;\r
465 }\r
466 #else\r
467 /*\r
468  * Check if the MemIf job is finished\r
469  */\r
470 \r
471 static boolean CheckMemIfJobFinished(void)\r
472 {\r
473         return MemIfJobAdmin.JobFinished;\r
474 }\r
475 \r
476 #endif\r
477 \r
478 \r
479 /*\r
480  * Abort the MemIf job with E_NOT_OK\r
481  */\r
482 static void AbortMemIfJob(MemIf_JobResultType jobResult)\r
483 {\r
484         MemIfJobAdmin.JobFinished = TRUE;\r
485         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
486         MemIfJobAdmin.JobResult = jobResult;\r
487 }\r
488 \r
489 #if 0\r
490 static boolean CheckJobFailed( void ) {\r
491         return CheckMemIfJobFinished() && (MemIfJobAdmin.JobResult == MEMIF_JOB_FAILED);\r
492 }\r
493 #endif\r
494 \r
495 /*\r
496  * Request a read of a block from MemIf
497  */\r
498 static void ReadBlock(const NvM_BlockDescriptorType *blockDescriptor,\r
499                                                         AdministrativeBlockType *adminBlock,\r
500                                                         uint8 setNumber,\r
501                                                         uint16 blockOffset,\r
502                                                         uint8 *destAddress,\r
503                                                         uint16 length )\r
504 {\r
505         Std_ReturnType returnCode;\r
506 \r
507         if (setNumber < blockDescriptor->NvBlockNum) {\r
508                 SetMemifJobBusy();\r
509                 MemIfJobAdmin.BlockAdmin = adminBlock;\r
510                 MemIfJobAdmin.BlockDescriptor = blockDescriptor;\r
511                 returnCode = MemIf_Read(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), blockOffset, destAddress, length );\r
512                 if (returnCode != E_OK) {\r
513                         AbortMemIfJob(MEMIF_JOB_FAILED);\r
514                 }\r
515         } else if (setNumber < blockDescriptor->NvBlockNum + blockDescriptor->RomBlockNum) {\r
516                 // TODO: Read from ROM\r
517         } else {\r
518                 // Error: setNumber out of range\r
519                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_READ_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);\r
520         }\r
521 }\r
522 \r
523 \r
524 /*\r
525  * Initiate the read all job
526  */\r
527 static void ReadAllInit(void)\r
528 {\r
529         /*\r
530          * Initiate the read all job
531          */\r
532         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
533         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
534         uint16 i;\r
535 \r
536         // Set status to pending in the administration blocks\r
537         AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING; /** @req 3.1.5/NVM304 */\r
538         AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;\r
539         AdminMultiReq.currBlockIndex = 0;\r
540 \r
541         for (i = 0; i < ( NVM_NUM_OF_NVRAM_BLOCKS ); i++) {\r
542                 if ((BlockDescriptorList->SelectBlockForReadall)\r
543 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)                                            /** @req NVM345 */\r
544                                 && ((!AdminBlockTable->BlockValid)                      // TODO: Check if this is to be done like this\r
545                                 || (!AdminBlockTable->BlockChanged))            // TODO: Check if this is to be done like this\r
546 #endif\r
547                                 ) {\r
548                         VALIDATE_NO_RV(BlockDescriptorList->RamBlockDataAddress != NULL, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);\r
549                         VALIDATE_NO_RV(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);\r
550 \r
551                         AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;\r
552                         AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;\r
553                 } else {\r
554                         AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED;   /* @req 3.1.5/NVM287 */\r
555                 }\r
556 \r
557                 AdminBlockTable++;\r
558                 BlockDescriptorList++;\r
559         }\r
560 }\r
561 \r
562 \r
563 static void writeCrcToBuffer(   void *bufPtr,\r
564                                                                 const NvM_BlockDescriptorType *bPtr,\r
565                                                                 AdministrativeBlockType *admPtr )\r
566 {\r
567         if( bPtr->BlockUseCrc ) {\r
568                 if(bPtr->BlockCRCType == NVM_CRC16) {\r
569                         WRITE16_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc16);\r
570                 } else {\r
571                         WRITE32_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc32);\r
572                 }\r
573         }\r
574 }\r
575 \r
576 \r
577 /*\r
578  * Drive the read state-machine\r
579  *\r
580  *\r
581  *\r
582  */\r
583 \r
584 static void DriveBlock( const NvM_BlockDescriptorType   *bPtr,\r
585                                                         AdministrativeBlockType *admPtr,\r
586                                                         void *dataPtr,\r
587                                                         boolean write,\r
588                                                         boolean multiBlock,\r
589                                                         boolean restoreFromRom )\r
590 {\r
591         bool blockDone = 0;\r
592         static uint8 driveBlockCnt = 0;\r
593 \r
594 \r
595         NVM_ASSERT( admPtr->ErrorStatus == NVM_REQ_PENDING);\r
596 \r
597         DEBUG_BLOCK_STATE("DriveBlock", BLOCK_NR_FROM_PTR(bPtr), admPtr->BlockState );\r
598 \r
599         switch (admPtr->BlockState) {\r
600         case BLOCK_STATE_MEMIF_REQ:\r
601         {\r
602                 void *ramData = (dataPtr != NULL) ?  dataPtr : bPtr->RamBlockDataAddress;\r
603 \r
604                 admPtr->savedDataPtr = ramData;\r
605 \r
606                 if( write ) {\r
607                         if( multiBlock && (dataPtr!=NULL)) {\r
608                                 NVM_ASSERT(0);\r
609                         }\r
610                         /* Copy to work buffer */\r
611                         memcpy( Nvm_WorkBuffer, ramData, bPtr->NvBlockLength );\r
612                         /* Add the CRC to write */\r
613                         writeCrcToBuffer(Nvm_WorkBuffer, bPtr, admPtr );\r
614                         WriteBlock(bPtr, admPtr, 0, Nvm_WorkBuffer);\r
615                 } else {\r
616                         uint8 crcLen = 0;\r
617                         /* Read to workbuffer */\r
618                         if( bPtr->BlockUseCrc ) {\r
619                                 crcLen = (bPtr->BlockCRCType == NVM_CRC16) ? 2: 4;\r
620                         }\r
621 \r
622                         if( restoreFromRom ) {\r
623                                 NVM_ASSERT( bPtr->RomBlockDataAdress != NULL );\r
624                                 /* No CRC on the ROM block */\r
625                                 memcpy(ramData,bPtr->RomBlockDataAdress,bPtr->NvBlockLength);\r
626 \r
627                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
628                                 blockDone = 1;\r
629                                 break;\r
630                         } else {\r
631                                 ReadBlock(bPtr, admPtr, 0, 0, bPtr->RamBlockDataAddress, bPtr->NvBlockLength+crcLen);\r
632                         }\r
633                 }\r
634 \r
635                 admPtr->BlockState = BLOCK_STATE_MEMIF_PROCESS;\r
636                 break;\r
637         }\r
638 \r
639         case BLOCK_STATE_MEMIF_PROCESS:\r
640         {\r
641                 /* Check read */\r
642                 MemIf_JobResultType jobResult = MemIf_GetJobResult(FIXME);\r
643 \r
644                 if( MEMIF_JOB_PENDING == jobResult ) {\r
645                         /* Keep on waiting */\r
646                 } else if( MEMIF_JOB_OK == jobResult ) {\r
647                         /* We are done */\r
648 \r
649 #if 0\r
650                         if( BLOCK_STATE_MEMIF_CRC_PROCESS == admPtr->BlockState ) {\r
651                                 /* @req 3.1.5/NVM362 NvM_ReadAll*/\r
652                                 DEBUG_CHECKSUM("RAM CRC", (bPtr->BlockCRCType == NVM_CRC16) ?  admPtr->RamCrc.crc16 : admPtr->RamCrc.crc32);\r
653                                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;\r
654                                 break;\r
655                         }\r
656 #endif\r
657 \r
658                         if( write ) {\r
659                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
660                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
661                                 blockDone = 1;\r
662 \r
663 #if 0\r
664                                 if( bPtr->BlockUseCrc ) {\r
665                                         /* Explicit CRC calc (not dependent on NvmCalcRamBlockCrc) */\r
666                                         /* @req 3.1.5/NVM212 NvM_WriteBlock */\r
667                                         /* @req 3.1.5/NVM253 NvM_WriteAll   */\r
668                                         admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;\r
669                                 } else {\r
670                                         /* Done */\r
671                                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
672                                         admPtr->ErrorStatus = NVM_REQ_OK;\r
673                                         blockDone = 1;\r
674                                 }\r
675 #endif\r
676                         } else {\r
677                                 /* read */\r
678                                 uint8 crcLen = 0;\r
679                                 if( bPtr->BlockUseCrc ) {\r
680 \r
681                                         /* The read data is in the work buffer, read the CRC */\r
682                                         if( bPtr->BlockCRCType == NVM_CRC16) {\r
683                                                 admPtr->NvCrc.crc16 = READ16_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );\r
684                                                 crcLen = 2;\r
685                                                 DEBUG_PRINTF(">> Nv CRC %04x\n",admPtr->NvCrc.crc16);\r
686                                                 admPtr->RamCrc.crc16 = admPtr->NvCrc.crc16;     /* Set RAM CRC = NvRAM CRC */\r
687                                         } else {\r
688                                                 admPtr->NvCrc.crc32 = READ32_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );\r
689                                                 crcLen = 4;\r
690                                                 DEBUG_PRINTF(">> Nv CRC %08x\n",admPtr->NvCrc.crc16);\r
691                                                 admPtr->RamCrc.crc32 = admPtr->NvCrc.crc32;     /* Set RAM CRC = NvRAM CRC */\r
692                                         }\r
693 \r
694                                         memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength  + crcLen );\r
695 \r
696                                         /* Check if we should re-calculate the RAM checksum now when it's in RAM */\r
697                                         if( bPtr->CalcRamBlockCrc ) {\r
698                                                 /* This block want its RAM block CRC checked */\r
699                                                 DEBUG_PRINTF(">> Recalculation of RAM checksum \n",admPtr->NvCrc.crc16);\r
700                                                 assert( bPtr->BlockUseCrc == 1);\r
701                                                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;\r
702                                         } else {\r
703                                                 /* Done */\r
704                                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
705                                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
706                                                 blockDone = 1;\r
707                                         }\r
708 \r
709                                 } else {\r
710                                         DEBUG_PRINTF(">> Block have NO CRC\n");\r
711 \r
712                                         memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength  + crcLen );\r
713                                         /* Done */\r
714                                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
715                                         admPtr->ErrorStatus = NVM_REQ_OK;\r
716                                         blockDone = 1;\r
717                                 }\r
718 \r
719                                 /* Copy from Workbuffer to the real buffer */\r
720 \r
721                         }\r
722                         break;\r
723                 } else {\r
724                         /* Something failed */\r
725                         AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;\r
726                         blockDone = 1;\r
727                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;     /* TODO, this really true for all result below */\r
728 \r
729                         switch( jobResult ) {\r
730                         case MEMIF_BLOCK_INVALID:\r
731                                 /* @req 3.1.5/NVM342 */\r
732                                 admPtr->ErrorStatus = NVM_REQ_NV_INVALIDATED;\r
733                                 break;\r
734                         case MEMIF_BLOCK_INCONSISTENT:\r
735                                 /* @req 3.1.5/NVM360 */\r
736                                 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;\r
737                                 DEM_REPORTERRORSTATUS(NVM_E_REQ_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);\r
738                                 break;\r
739                         case MEMIF_JOB_FAILED:\r
740                                 /* @req 3.1.5/NVM361 */\r
741                                 admPtr->ErrorStatus = NVM_REQ_NOT_OK;\r
742                                 DEM_REPORTERRORSTATUS(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);\r
743                         default:\r
744                                 NVM_ASSERT(0);\r
745                                 break;\r
746                         }\r
747                 }\r
748                 break;\r
749         }\r
750 \r
751         case BLOCK_STATE_CALC_CRC:\r
752                 NVM_ASSERT(0);\r
753                 break;\r
754 \r
755         case BLOCK_STATE_CALC_CRC_WRITE:\r
756         {\r
757                 uint16 crc16;\r
758                 uint32 crc32;\r
759                 NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );\r
760 \r
761                 /* Calculate RAM CRC checksum */\r
762                 if( bPtr->BlockCRCType == NVM_CRC16 ) {\r
763 \r
764                         crc16 = Crc_CalculateCRC16(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffff);\r
765                         DEBUG_CHECKSUM("RAM",crc16);\r
766 \r
767                         /* Just save the checksum */\r
768                         admPtr->RamCrc.crc16 = crc16;\r
769 \r
770 #if 0\r
771                         /* NV CRC in admin block */\r
772                         if( admPtr->RamCrc.crc16 != crc16 ) {\r
773                                 NVM_ASSERT(0);          /* TODO: Corrupt CRC */\r
774                         } else {\r
775                                 admPtr->BlockChanged = BLOCK_STATE_MEMIF_REQ;\r
776                         }\r
777 #endif\r
778 \r
779                         /* Write the block */\r
780                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
781                 } else {\r
782                         /* @req 3.1.5/NVM253 */\r
783                         crc32 = Crc_CalculateCRC32(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffffffffUL);\r
784                         if( crc32 !=  admPtr->RamCrc.crc32 ) {\r
785                                 /* The checksum is wrong, something have written to the RAM area without\r
786                                  * telling the NVM */\r
787                                 NVM_ASSERT(0);\r
788                         } else {\r
789                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
790                         }\r
791                         admPtr->RamCrc.crc32 = crc32;\r
792                 }\r
793                 break;\r
794         }\r
795         case BLOCK_STATE_CALC_CRC_READ:\r
796         {\r
797                 NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );\r
798                 NVM_ASSERT(bPtr->CalcRamBlockCrc == true );\r
799                 uint16 crc16;\r
800                 uint32 crc32;\r
801 \r
802                 /* Calculate RAM CRC checksum */\r
803                 if( bPtr->BlockCRCType == NVM_CRC16 ) {\r
804 \r
805 \r
806                         crc16 = Crc_CalculateCRC16(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffff);\r
807                         DEBUG_CHECKSUM("RAM",crc16);\r
808 \r
809                         /* NV CRC in admin block */\r
810 \r
811                         if( driveBlockCnt == 1) {\r
812                                 /* The previous "loop" we filled with default data */\r
813                                 admPtr->RamCrc.crc16 = crc16;\r
814                         }\r
815 \r
816                         /* @req 3.1.5/NVM387 */\r
817                         if( admPtr->RamCrc.crc16 != crc16 ) {\r
818 \r
819                                 /* @req 3.1.5/NVM388 Nvm_ReadAll */\r
820 \r
821                                 /* NVM387, NVM388\r
822                                  *\r
823                                  * Corrupt CRC, what choices are there:\r
824                                  * 1. Default data (=ROM) configured, just copy it.\r
825                                  * 2. Data redundancy, get it.\r
826                                  * 3. None of the above. Catastrophic failure. (NVM203)\r
827                                  */\r
828                                 if( bPtr->RomBlockDataAdress != NULL ) {\r
829                                         /* TODO: Restore block from ROM */\r
830                                         NVM_ASSERT(0);\r
831                                 } else {\r
832                                         /* @req 3.1.5/NVM469 */\r
833                                         if( bPtr->InitBlockCallback != NULL ) {\r
834 \r
835                                                 DEBUG_PRINTF("Filling block with default data\n");\r
836                                                 bPtr->InitBlockCallback();\r
837                                                 driveBlockCnt++;\r
838                                                 /* NVM085 is very vague here, but the says the application should be\r
839                                                  * able distinguish between when the init-callback have been called\r
840                                                  * or CRC is corrupt.\r
841                                                  */\r
842 \r
843                                                 /* The RAM CRC is at this point not calculated...so we must do this\r
844                                                  * .. so just stay in this state one more MainFunction.\r
845                                                  * */\r
846 \r
847                                         } else {\r
848 \r
849                                                 /* @req 3.1.5/NVM203 */\r
850                                                 DEM_REPORTERRORSTATUS(NVM_E_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);\r
851                                                 /* @req 3.1.5/NVM204 */\r
852                                                 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;\r
853                                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
854                                                 blockDone = 1;\r
855                                         }\r
856                                 }\r
857                         } else {\r
858                                 DEBUG_CHECKSUM("RAM checksum ok with ",crc16);\r
859                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
860                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
861                                 blockDone = 1;\r
862                         }\r
863 \r
864                 } else {\r
865                         /* @req 3.1.5/NVM253 */\r
866                         /* Calculate CRC on the data we just read to RAM. Compare with CRC that is located in NV block */\r
867                         crc32 = Crc_CalculateCRC32(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffffffffUL);\r
868                         if( crc32 !=  admPtr->RamCrc.crc32 ) {\r
869                                 NVM_ASSERT(0);  /* TODO: Corrupt CRC */\r
870                         } else {\r
871                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
872                         }\r
873                 }\r
874                 break;\r
875         }\r
876         default:\r
877                 NVM_ASSERT(0);\r
878                 break;\r
879         }\r
880 \r
881         if( blockDone  ) {\r
882 \r
883                 DEBUG_PRINTF("# Block Done\n");\r
884 \r
885                 if( admPtr->ErrorStatus == NVM_REQ_OK ) {\r
886                         admPtr->BlockChanged = FALSE;\r
887                         admPtr->BlockValid = TRUE;\r
888                 }\r
889 \r
890 \r
891                 /*  @req 3.1.5/NVM281 */\r
892                 if( bPtr->SingleBlockCallback != NULL ) {\r
893                         bPtr->SingleBlockCallback(NVM_READ_ALL_ID, admPtr->ErrorStatus);\r
894                 }\r
895 \r
896                 if( multiBlock ) {\r
897                         AdminMultiReq.currBlockIndex++;\r
898                         if( AdminMultiReq.currBlockIndex >= NVM_NUM_OF_NVRAM_BLOCKS ) {\r
899                                 AdminMultiReq.currBlockIndex = 0;\r
900 \r
901                                 /* @req 3.1.5/NVM301 */\r
902                                 if( NVM_REQ_NOT_OK == AdminMultiReq.PendingErrorStatus ) {\r
903                                         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
904                                 } else {\r
905                                         AdminMultiBlock.ErrorStatus = NVM_REQ_OK;\r
906                                 }\r
907                                 nvmState = NVM_IDLE;\r
908                                 nvmSubState = 0;\r
909                         }\r
910                 } else {\r
911                         nvmState = NVM_IDLE;\r
912                         nvmSubState = 0;\r
913 \r
914                 }\r
915         }\r
916 }\r
917 \r
918 /*\r
919  * Main function for the read all job
920  */\r
921 static void ReadAllMain(void)\r
922 {\r
923 \r
924         /* Cases:\r
925          * 1. We process each block until it's finished\r
926          * 2. We start to process a lot of blocks. The blocks may use different devices\r
927          *    and should be able to read a lot of them. This includes CRC.\r
928          *\r
929          *    1) is much simpler and 2) probably much faster.\r
930          *    This implementation will use 1) since it's simpler and maximum time that is\r
931          *    spent in MainFunction() can be controlled much better.\r
932          */\r
933 \r
934         /* Skip blocks that are skipped */\r
935 \r
936         while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {\r
937                 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {\r
938                         AdminMultiReq.currBlockIndex++;\r
939                 } else {\r
940                         return;\r
941                 }\r
942         }\r
943 \r
944         DriveBlock(     &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],\r
945                                         &AdminBlock[AdminMultiReq.currBlockIndex],\r
946                                         NULL,\r
947                                         false,\r
948                                         true, false);\r
949 }\r
950 \r
951 \r
952 /*\r
953  * Request writing of a block to MemIf
954  */\r
955 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,\r
956                                                 AdministrativeBlockType *adminBlock,\r
957                                                 uint8 setNumber,\r
958                                                 uint8 *sourceAddress)\r
959 {\r
960         Std_ReturnType returnCode;\r
961 \r
962         if (setNumber < blockDescriptor->NvBlockNum) {\r
963                 SetMemifJobBusy();\r
964                 MemIfJobAdmin.BlockAdmin = adminBlock;\r
965                 MemIfJobAdmin.BlockDescriptor = blockDescriptor;\r
966                 returnCode = MemIf_Write(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), sourceAddress);\r
967                 if (returnCode != E_OK) {\r
968                         AbortMemIfJob(MEMIF_JOB_FAILED);\r
969                 }\r
970         } else {\r
971                 // Error: setNumber out of range\r
972                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_WRITE_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);\r
973         }\r
974 }\r
975 \r
976 \r
977 \r
978 /*\r
979  * Initiate the write all job\r
980  */\r
981 static void WriteAllInit(void)\r
982 {\r
983         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
984         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
985         uint16 i;\r
986 \r
987 //      nvmState = NVM_WRITE_ALL_PROCESSING;\r
988         AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;\r
989         AdminMultiReq.currBlockIndex = 0;\r
990 \r
991         for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
992                 if ((BlockDescriptorList->RamBlockDataAddress != NULL)\r
993 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)                                            /** @req NVM344 */\r
994                                 && (AdminBlockTable->BlockValid)                                        /** @req NVM682 */\r
995                                 && (AdminBlockTable->BlockChanged)                                      /** @req NVM682 */\r
996 #endif\r
997                                 && (!AdminBlockTable->BlockWriteProtected))                     /** @req NVM432 *//** @req NVM433 */\r
998                 {\r
999                         AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;\r
1000 \r
1001                         if (BlockDescriptorList->BlockUseCrc) {\r
1002                                 AdminBlockTable->BlockState = BLOCK_STATE_CALC_CRC_WRITE;       /** @req NVM253 */\r
1003                         } else {\r
1004                                 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1005                                 AdminBlockTable->NumberOfWriteFailed = 0;\r
1006                         }\r
1007                 } else {\r
1008                         AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED;   /** @req NVM298 */\r
1009                 }\r
1010 \r
1011                 AdminBlockTable++;\r
1012                 BlockDescriptorList++;\r
1013         }\r
1014 }\r
1015 \r
1016 \r
1017 \r
1018 /*\r
1019  * Main function for the write all job\r
1020  */\r
1021 static void WriteAllMain(void)\r
1022 {\r
1023 \r
1024         while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {\r
1025                 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {\r
1026                         AdminMultiReq.currBlockIndex++;\r
1027                 } else {\r
1028                         return;\r
1029                 }\r
1030         }\r
1031 \r
1032         DriveBlock(     &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],\r
1033                                         &AdminBlock[AdminMultiReq.currBlockIndex],\r
1034                                         NULL,\r
1035                                         true,\r
1036                                         true, false );\r
1037 \r
1038 }\r
1039 \r
1040 \r
1041 #if 0\r
1042 /*\r
1043  * Handles the result of one MemIf block write\r
1044  */\r
1045 static void WriteAllCheckWriteResult(void)\r
1046 {\r
1047         if (MemIfJobAdmin.JobStatus == E_OK) {\r
1048                 // TODO: Check if redundant block shall be written NVM337\r
1049 \r
1050                 if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {\r
1051                         MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE;   /** @req NVM329 */\r
1052                 }\r
1053                 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1054                 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;\r
1055 \r
1056                 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
1057                         (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);\r
1058                 }\r
1059         } else {\r
1060                 MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed++;\r
1061                 if (MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES) {\r
1062                         // TODO: Check if redundant block shall be written NVM337\r
1063 \r
1064                         // Write has failed\r
1065                         AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;\r
1066 \r
1067                         MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1068                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK; /** @req NVM296 */\r
1069 #if defined(USE_DEM)\r
1070                         Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);\r
1071 #endif\r
1072 \r
1073                         if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
1074                                 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);\r
1075                         }\r
1076                 }\r
1077         }\r
1078         nvmState = NVM_WRITE_ALL_PROCESSING;\r
1079 }\r
1080 #endif\r
1081 \r
1082 \r
1083 \r
1084 /***************************************\r
1085  *    External accessible functions    *\r
1086  ***************************************/\r
1087 /*\r
1088  * Procedure:   NvM_Init\r
1089  * Reentrant:   No\r
1090  */\r
1091 void NvM_Init(void)\r
1092 {\r
1093         /** @req NVM399 *//** @req NVM193 */\r
1094         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
1095         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
1096         uint16 i;\r
1097 \r
1098 \r
1099         CirqBuff_Init(&nvmQueue,nvmQueueData,sizeof(nvmQueueData),sizeof(Nvm_QueueType));\r
1100 \r
1101         // Initiate the administration blocks\r
1102         for (i = 0; i< NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
1103                 if (BlockDescriptorList->BlockManagementType == NVM_BLOCK_DATASET) {\r
1104                         AdminBlockTable->DataIndex = 0; /** @req NVM192 */\r
1105                 }\r
1106                 AdminBlockTable->BlockWriteProtected = BlockDescriptorList->BlockWriteProt;\r
1107                 AdminBlockTable->ErrorStatus = NVM_REQ_NOT_OK;\r
1108                 AdminBlockTable->BlockChanged = FALSE;\r
1109                 AdminBlockTable->BlockValid = FALSE;\r
1110                 AdminBlockTable->NumberOfWriteFailed = 0;\r
1111 \r
1112                 AdminBlockTable++;\r
1113                 BlockDescriptorList++;\r
1114         }\r
1115 \r
1116         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
1117 \r
1118         // Set status to initialized\r
1119         nvmState = NVM_IDLE;    /** @req 3.1.5/NVM399 */\r
1120 }\r
1121 \r
1122 \r
1123 /*\r
1124  * Procedure:   NvM_ReadAll\r
1125  * Reentrant:   No\r
1126  */\r
1127 void NvM_ReadAll(void)\r
1128 {\r
1129         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);\r
1130 \r
1131         NVM_ASSERT(nvmState == NVM_IDLE);\r
1132 \r
1133         AdminMultiReq.state = NVM_READ_ALL;\r
1134         AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;\r
1135 }\r
1136 \r
1137 \r
1138 \r
1139 /*\r
1140  * Procedure:   NvM_WriteAll\r
1141  * Reentrant:   No\r
1142  */\r
1143 void NvM_WriteAll(void)\r
1144 {\r
1145         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);\r
1146 \r
1147         NVM_ASSERT(nvmState == NVM_IDLE);\r
1148 \r
1149         AdminMultiReq.state = NVM_WRITE_ALL;\r
1150         AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;\r
1151 }\r
1152 \r
1153 \r
1154 /*\r
1155  * Procedure:   NvM_CancelWriteAll\r
1156  * Reentrant:   No\r
1157  */\r
1158 void NvM_CancelWriteAll(void)\r
1159 {\r
1160         \r
1161 }\r
1162 \r
1163 \r
1164 /*\r
1165  * Procedure:   NvM_GetErrorStatus\r
1166  * Reentrant:   Yes\r
1167  */\r
1168 void NvM_GetErrorStatus(NvM_BlockIdType blockId, uint8 *requestResultPtr)\r
1169 {\r
1170         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_ERROR_STATUS_ID, NVM_E_NOT_INITIALIZED);\r
1171         VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_ERROR_STATUS_ID, NVM_E_PARAM_BLOCK_ID);\r
1172 \r
1173         if (blockId == 0) {\r
1174                 // Multiblock ID\r
1175                 *requestResultPtr = AdminMultiBlock.ErrorStatus;\r
1176         } else if (blockId == 1) {\r
1177                 /* TODO */\r
1178           *requestResultPtr = NVM_REQ_OK;\r
1179         } else {\r
1180                 *requestResultPtr = AdminBlock[blockId-1].ErrorStatus;\r
1181         }\r
1182 \r
1183 }\r
1184 \r
1185 \r
1186 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)    /** @req NVM408 */\r
1187 /*\r
1188  * Procedure:   Nvm_SetRamBlockStatus\r
1189  * Reentrant:   Yes\r
1190  */\r
1191 void NvM_SetRamBlockStatus(NvM_BlockIdType blockId, boolean blockChanged)\r
1192 {\r
1193         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
1194 \r
1195         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_NOT_INITIALIZED);      /** @req NVM497 */\r
1196         VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);\r
1197         VALIDATE_NO_RV(blockId > 1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);\r
1198 \r
1199         if (BlockDescriptorList[blockId-1].RamBlockDataAddress != NULL) {       /** @req NVM240 */\r
1200                 if (blockChanged) {\r
1201                         AdminBlock[blockId-1].BlockChanged = TRUE;      /** @req NVM406 */\r
1202                         AdminBlock[blockId-1].BlockValid = TRUE;        /** @req NVM241 */\r
1203                         if (BlockDescriptorList[blockId-1].BlockUseCrc) {\r
1204                                 AdminBlock[blockId-1].BlockState = BLOCK_STATE_CALC_CRC;        /** @req NVM121 */\r
1205                         }\r
1206                 } else {\r
1207                         AdminBlock[blockId-1].BlockChanged = FALSE;     /** @req NVM405 */\r
1208                         AdminBlock[blockId-1].BlockValid = FALSE;\r
1209                 } // else blockChanged\r
1210         } // if permanent block\r
1211 }\r
1212 #endif\r
1213 \r
1214 \r
1215 void NvM_SetBlockLockStatus( NvM_BlockIdType blockId, boolean blockLocked ) {\r
1216         (void)blockId;\r
1217         (void)blockLocked;\r
1218 }\r
1219 \r
1220 \r
1221 /**\r
1222  * Restore default data to its corresponding RAM block.\r
1223  *
1224  * @param BlockId               NVRAM block identifier.
1225  * @param NvM_DestPtr   Pointer to the RAM block
1226  * @return
1227  */\r
1228 Std_ReturnType NvM_RestoreBlockDefaults( NvM_BlockIdType blockId, uint8* NvM_DestPtr )\r
1229 {\r
1230         /* !req 3.1.5/NVM012 */ /* !req 3.1.5/NVM267 */ /* !req 3.1.5/NVM266 */\r
1231         /* !req 3.1.5/NVM353 */ /* !req 3.1.5/NVM435 */ /* !req 3.1.5/NVM436 */ /* !req 3.1.5/NVM227 */\r
1232         /* !req 3.1.5/NVM228 */ /* !req 3.1.5/NVM229 */ /* !req 3.1.5/NVM413 */\r
1233 \r
1234         const NvM_BlockDescriptorType * bPtr;\r
1235         AdministrativeBlockType *               admPtr;\r
1236         Nvm_QueueType qEntry;\r
1237         int rv;\r
1238 \r
1239         NVM_ASSERT( blockId >= 2 );     /* No support for lower numbers, yet */\r
1240 \r
1241         /* @req 3.1.5/NVM618 */\r
1242         VALIDATE_RV(    blockId <= NVM_NUM_OF_NVRAM_BLOCKS,\r
1243                                         NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );\r
1244 \r
1245         bPtr = &NvM_Config.BlockDescriptor[blockId-1];\r
1246         admPtr = &AdminBlock[blockId-1];\r
1247 \r
1248         /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */\r
1249         if( (NvM_DestPtr == NULL) &&  ( bPtr->RamBlockDataAddress == NULL ) ) {\r
1250                 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */\r
1251                 NVM_ASSERT(0);          // TODO: See NVM210, DET error\r
1252                 return E_NOT_OK;\r
1253         }\r
1254 \r
1255         /* @req 3.1.5/NVM195 */\r
1256         qEntry.blockId = blockId;\r
1257         qEntry.op = NVM_RESTORE_BLOCK_DEFAULTS;\r
1258         qEntry.blockId = blockId;\r
1259         qEntry.dataPtr = (uint8_t *)NvM_DestPtr;\r
1260         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1261         NVM_ASSERT(rv == 0 );\r
1262 \r
1263         /* @req 3.1.5/NVM620 */\r
1264         VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1265 \r
1266         /* req 3.1.5/NVM185 */\r
1267         admPtr->ErrorStatus = NVM_REQ_PENDING;\r
1268 \r
1269         if( bPtr->BlockUseCrc) {\r
1270                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;\r
1271         } else {\r
1272                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1273         }\r
1274 \r
1275 \r
1276         return E_OK;\r
1277 }\r
1278 \r
1279 /**\r
1280  * Service to copy the data NV block to the RAM block\r
1281  *
1282  * @param blockId               0 and 1 reserved. The block ID are sequential.
1283  * @param NvM_DstPtr
1284  * @return
1285  */\r
1286 \r
1287 \r
1288 Std_ReturnType NvM_ReadBlock( NvM_BlockIdType blockId, uint8* NvM_DstPtr )\r
1289 {\r
1290         /* !req 3.1.5/NVM010 */\r
1291 \r
1292 \r
1293         /* !req 3.1.5/NVM278 */\r
1294         /* !req 3.1.5/NVM340 */\r
1295         /* !req 3.1.5/NVM354 */\r
1296         /* !req 3.1.5/NVM200 */\r
1297         /* !req 3.1.5/NVM366 */\r
1298         /* !req 3.1.5/NVM206 */\r
1299         /* !req 3.1.5/NVM341 */\r
1300         /* !req 3.1.5/NVM358 */\r
1301         /* !req 3.1.5/NVM359 */\r
1302         /* !req 3.1.5/NVM279 */\r
1303         /* !req 3.1.5/NVM316 */\r
1304         /* !req 3.1.5/NVM317 */\r
1305         /* !req 3.1.5/NVM201 */\r
1306         /* !req 3.1.5/NVM202 */\r
1307         /* !req 3.1.5/NVM203 */\r
1308         /* !req 3.1.5/NVM204 */\r
1309         /* !req 3.1.5/NVM409 */\r
1310 \r
1311 \r
1312    /* logical block:\r
1313     *\r
1314     *    1 1 1 1 1 1\r
1315     *   |5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|\r
1316     *    b b b b b b b b b b d d d d d d\r
1317     *\r
1318     * Here we have 10 bits for block id, 16-5 for DataSetSelection bits.\r
1319     * - 2^10, 1024 blocks\r
1320     * - 64 datasets for each NVRAM block\r
1321     *\r
1322     * How are the block numbers done in EA? Assume virtual page=8\r
1323     * logical\r
1324     *  Block   size\r
1325     *  1       32\r
1326     *   2\r
1327     *   3\r
1328     *   4\r
1329     *  5       12\r
1330     *   6\r
1331     *  7\r
1332     *\r
1333     *  How can NVM/NvmNvBlockLength and EA/EaBlockSize be different?\r
1334     *  It seems that EA/FEE does not care about that logical block 2 above is\r
1335     *  "blocked"\r
1336     *
1337     */\r
1338         Nvm_QueueType qEntry;\r
1339         int rv;\r
1340 \r
1341         /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */\r
1342         if( (NvM_DstPtr == NULL) &&  ( NvM_Config.BlockDescriptor[blockId-1].RamBlockDataAddress == NULL ) ) {\r
1343                 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */\r
1344                 return E_NOT_OK;\r
1345         }\r
1346 \r
1347         /* @req 3.1.5/NVM195 */\r
1348         qEntry.blockId = blockId;\r
1349         qEntry.op = NVM_READ_BLOCK;\r
1350         qEntry.blockId = blockId;\r
1351         qEntry.dataPtr = NvM_DstPtr;\r
1352         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1353         NVM_ASSERT(rv == 0 );\r
1354 \r
1355         /* @req 3.1.5/NVM615 */\r
1356         VALIDATE_RV( (AdminBlock[blockId-1].ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1357 \r
1358         /* req 3.1.5/NVM185 */\r
1359         AdminBlock[blockId-1].ErrorStatus = NVM_REQ_PENDING;\r
1360 \r
1361         return E_OK;\r
1362 }\r
1363 \r
1364 \r
1365 /**\r
1366  * Service to copy a RAM block to its correspnding NVRAM block\r
1367  *
1368  * @param blockId
1369  * @param NvM_SrcPtr
1370  * @return
1371  */\r
1372 Std_ReturnType NvM_WriteBlock( NvM_BlockIdType blockId, const uint8* NvM_SrcPtr ) {\r
1373 \r
1374         const NvM_BlockDescriptorType * bPtr;\r
1375         AdministrativeBlockType *               admPtr;\r
1376         Nvm_QueueType qEntry;\r
1377         int rv;\r
1378 \r
1379         NVM_ASSERT( blockId >= 2 );     /* No support for lower numbers, yet */\r
1380 \r
1381         /* @req 3.1.5/NVM618 */\r
1382         VALIDATE_RV(    blockId <= NVM_NUM_OF_NVRAM_BLOCKS,\r
1383                                         NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );\r
1384 \r
1385         bPtr = &NvM_Config.BlockDescriptor[blockId-1];\r
1386         admPtr = &AdminBlock[blockId-1];\r
1387 \r
1388         /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */\r
1389         if( (NvM_SrcPtr == NULL) &&  ( bPtr->RamBlockDataAddress == NULL ) ) {\r
1390                 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */\r
1391                 NVM_ASSERT(0);          // TODO: See NVM210, DET error\r
1392                 return E_NOT_OK;\r
1393         }\r
1394 \r
1395         /* @req 3.1.5/NVM195 */\r
1396         qEntry.blockId = blockId;\r
1397         qEntry.op = NVM_WRITE_BLOCK;\r
1398         qEntry.blockId = blockId;\r
1399         qEntry.dataPtr = (uint8_t *)NvM_SrcPtr;\r
1400         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1401         NVM_ASSERT(rv == 0 );\r
1402 \r
1403         /* @req 3.1.5/NVM620 */\r
1404         VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1405 \r
1406         /* req 3.1.5/NVM185 */\r
1407         admPtr->ErrorStatus = NVM_REQ_PENDING;\r
1408 \r
1409         if( bPtr->BlockUseCrc) {\r
1410                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;\r
1411         } else {\r
1412                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1413         }\r
1414 \r
1415 \r
1416         return E_OK;\r
1417 }\r
1418 \r
1419 /* Missing from Class 2\r
1420  * - NvM_CancelWriteAll\r
1421  * - NvM_SetDataIndex\r
1422  * - NvM_GetDataIndex\r
1423  * */\r
1424 \r
1425 \r
1426 \r
1427 \r
1428 \r
1429 const NvM_BlockDescriptorType * nvmBlock;\r
1430 AdministrativeBlockType *admBlock;\r
1431 \r
1432 /**\r
1433  *
1434  */\r
1435 void NvM_MainFunction(void)\r
1436 {\r
1437         int                     rv;\r
1438         Nvm_QueueType   qEntry;\r
1439         const NvM_BlockDescriptorType * bList = NvM_Config.BlockDescriptor;\r
1440 //      const NvM_BlockDescriptorType * currBlock;\r
1441 //      static uint32 crc32;\r
1442 //      static uint32 crc32Left;\r
1443 \r
1444         /* Check for new requested state changes */\r
1445         if( nvmState == NVM_IDLE ) {\r
1446                 rv = CirqBuffPop( &nvmQueue, &qEntry );\r
1447                 if( rv == 0 ) {\r
1448                         /* Found something in buffer */\r
1449                         nvmState = qEntry.op;\r
1450                         nvmBlock = &bList[qEntry.blockId-1];\r
1451                         admBlock = &AdminBlock[qEntry.blockId-1];\r
1452                         nvmSubState = 0;\r
1453                         admBlock->ErrorStatus = NVM_REQ_PENDING;\r
1454                         DEBUG_PRINTF("### Popped Single FIFO \n");\r
1455                         DEBUG_PRINTF("### CRC On:%d Ram:%d Type:%d\n",nvmBlock->BlockUseCrc, nvmBlock->CalcRamBlockCrc, nvmBlock->BlockCRCType );\r
1456                         DEBUG_PRINTF("### RAM:%x ROM:%x\n", nvmBlock->RamBlockDataAddress, nvmBlock->RomBlockDataAdress );\r
1457                 } else {\r
1458                         /* Check multiblock req */\r
1459                         if( AdminMultiReq.state != NVM_UNINITIALIZED ) {\r
1460                                 nvmState = AdminMultiReq.state ;\r
1461                                 nvmSubState = 0;\r
1462                                 nvmBlock = 0;\r
1463                                 admBlock = 0;\r
1464                                 AdminMultiReq.state = NVM_UNINITIALIZED;\r
1465 \r
1466                                 DEBUG_PRINTF("### Popped MULTI\n");\r
1467                         }\r
1468                 }\r
1469         }\r
1470 \r
1471         DEBUG_STATE(nvmState,nvmSubState);\r
1472 \r
1473         switch (nvmState) {\r
1474         case NVM_UNINITIALIZED:\r
1475                 break;\r
1476 \r
1477         case NVM_IDLE:\r
1478         {\r
1479                 CalcCrc();\r
1480                 break;\r
1481         }\r
1482         case NVM_READ_ALL:\r
1483                 if( NS_INIT == nvmSubState ) {\r
1484                         ReadAllInit();\r
1485                         nvmSubState = NS_PROSSING;\r
1486                 } else if( NS_PROSSING == nvmSubState ) {\r
1487                         ReadAllMain();\r
1488                 }\r
1489                 break;\r
1490 \r
1491         case NVM_READ_BLOCK:\r
1492                 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, false );\r
1493                 break;\r
1494 \r
1495         case NVM_RESTORE_BLOCK_DEFAULTS:\r
1496                 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, true );\r
1497                 break;\r
1498 \r
1499         case NVM_WRITE_BLOCK:\r
1500                 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, true /*write*/, false , false );\r
1501                 break;\r
1502 \r
1503         case NVM_WRITE_ALL:\r
1504                 if( NS_INIT == nvmSubState ) {\r
1505                         WriteAllInit();\r
1506                         nvmSubState = NS_PROSSING;\r
1507                 } else if( NS_PROSSING == nvmSubState ) {\r
1508                         WriteAllMain();\r
1509                 }\r
1510                 break;\r
1511 \r
1512         default:\r
1513                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_MAIN_FUNCTION_ID, NVM_UNEXPECTED_STATE);\r
1514                 break;\r
1515         }\r
1516 }\r
1517 \r
1518 \r
1519 /***************************************\r
1520  *  Call-back notifications functions  *\r
1521  ***************************************/\r
1522 #if (NVM_POLLING_MODE == STD_OFF)\r
1523 /*\r
1524  * Procedure:   NvM_JobEndNotification\r
1525  * Reentrant:   No\r
1526  */\r
1527 void NvM_JobEndNotification(void)\r
1528 {\r
1529         MemIfJobAdmin.JobFinished = TRUE;\r
1530         MemIfJobAdmin.JobStatus = E_OK;\r
1531         MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);\r
1532 }\r
1533 \r
1534 /*\r
1535  * Procedure:   NvM_JobErrorNotification\r
1536  * Reentrant:   No\r
1537  */\r
1538 void NvM_JobErrorNotification(void)\r
1539 {\r
1540         MemIfJobAdmin.JobFinished = TRUE;\r
1541         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
1542         MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);\r
1543 }\r
1544 #endif\r
1545 \r