FreeCalypso > hg > tcs211-l1-reconst
comparison chipsetsw/riviera/rvf/rvf_buffer.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:509db1a7b7b8 |
---|---|
1 /****************************************************************************/ | |
2 /* */ | |
3 /* Name rvf_buffer.c */ | |
4 /* */ | |
5 /* Function this file contains rvf buffer handling functions */ | |
6 /* */ | |
7 /* Version 0.1 */ | |
8 /* */ | |
9 /* Date Modification */ | |
10 /* ------------------------------------ */ | |
11 /* 3/12/99 Create */ | |
12 /* 10/27/1999 remove all non-nucleus sections (#ifdef) */ | |
13 /* 30/11/1999 compliant to RV coding guidelines */ | |
14 /* 12/23/1999 change buffer management, add memory bank handling and */ | |
15 /* remove useless functions */ | |
16 /* 07/12/2000 implement dynamic memory allocation. */ | |
17 /* */ | |
18 /* Author David Lamy-Charrier (dlamy@tif.ti.com) */ | |
19 /* */ | |
20 /* (C) Copyright 1999 by Texas Instruments Incorporated, All Rights Reserved*/ | |
21 /****************************************************************************/ | |
22 | |
23 #ifndef _WINDOWS | |
24 #include "config/board.cfg" | |
25 #endif | |
26 | |
27 #include "nucleus.h" | |
28 #include "rvm/rvm_use_id_list.h" | |
29 #include "rvf/rvf_api.h" | |
30 #include "rvf/rvf_i.h" | |
31 #include "support/exception.h" | |
32 #include "rvf/rvf_pool_size.h" | |
33 | |
34 #include <string.h> | |
35 #include <stdio.h> | |
36 | |
37 | |
38 #if RVF_ENABLE_STATS /* conditional inclusion of stdio.h for sprintf() function */ | |
39 #ifdef _WINDOWS | |
40 #include <stdio.h> | |
41 #endif | |
42 #endif | |
43 | |
44 #include "rv/rv_defined_swe.h" | |
45 | |
46 #ifdef RVM_DAR_SWE | |
47 #include "dar/dar_api.h" | |
48 #endif | |
49 #define RVF_INVALID_MD_ID_ERRROR ("RVF: Invalid MB ID") | |
50 | |
51 #define INC_END_INITIALIZE 2 | |
52 #define RVF_INVALID_INDEX 0xFFFF | |
53 | |
54 /************* TASK MAILBOXES *******************/ | |
55 /* chained lists for task mailboxes */ | |
56 T_RVF_INTERNAL_BUF *OSTaskQFirst[1][1]; //[MAX_RVF_TASKS][RVF_NUM_TASK_MBOX]; | |
57 T_RVF_INTERNAL_BUF *OSTaskQLast [1][1]; //[MAX_RVF_TASKS][RVF_NUM_TASK_MBOX]; | |
58 | |
59 extern INC_Initialize_State; | |
60 | |
61 T_RVF_RT_ADDR_ID_DATA* pRtAddrIdTable[MAX_RVF_G_ADDR_ID]; | |
62 | |
63 | |
64 /******** MEMORY POOLS ******************/ | |
65 /* Define the buffer pools */ | |
66 extern T_RVF_POOL _rvf_pools[]; | |
67 | |
68 /*********** MEMORY BANKS ***********/ | |
69 /* array of memory bank */ | |
70 static T_RVF_MB rvf_banks[RVF_MAX_REAL_MB]; | |
71 | |
72 /* array of waiting buffers */ | |
73 static T_RVF_BUFFER * waiting_buffers[RVF_MAX_WAITING_BUF]; | |
74 static UINT16 next_buffer[RVF_MAX_WAITING_BUF]; | |
75 static UINT16 first_free_element; | |
76 | |
77 /* array of memory bank name and id*/ | |
78 static T_RVF_MB_NAME_ID rvf_name_id[RVF_MAX_TOTAL_MB] = RVF_MB_MAPPING; | |
79 | |
80 | |
81 /* variable for statistics */ | |
82 #if RVF_ENABLE_STATS | |
83 static UINT32 required_size = 0; | |
84 static UINT32 obtained_size = 0; | |
85 static UINT32 used_size = 0; | |
86 static UINT32 mem_in_use = 0; | |
87 #endif | |
88 | |
89 /* lists of free buffers */ | |
90 static T_RVF_INTERNAL_BUF * lists[RVF_NB_FREE_LISTS]; | |
91 | |
92 /* last split-off buffer */ | |
93 T_RVF_INTERNAL_BUF * last_remainder = NULL; | |
94 | |
95 /* allocated static buffer pools */ | |
96 extern UINT8 Buf0[]; | |
97 extern UINT8 Buf1[]; | |
98 | |
99 /********Internal windows function used to display memory status *******/ | |
100 #ifdef _WINDOWS | |
101 extern void AddNewState(void *s,char *name, | |
102 unsigned long current,unsigned long peak, | |
103 unsigned long water,unsigned long bank); | |
104 #endif | |
105 | |
106 | |
107 /******************************************************************************* | |
108 ** | |
109 ** Function _rvf_init_free_queue | |
110 ** | |
111 ** Description Function called at startup to initialize a free | |
112 ** pool (statically or dynamically allocated). | |
113 ** It is called once for each free pool. | |
114 ** | |
115 ** Returns void | |
116 ** | |
117 *******************************************************************************/ | |
118 void _rvf_init_free_queue (UINT8 id, UINT32 size, void *p_mem) | |
119 { | |
120 T_RVF_INTERNAL_BUF *hdr; | |
121 UINT8 list_idx; | |
122 | |
123 /* round to up size to a multiple of 4 */ | |
124 size = (size + 3) & ~0x0003; | |
125 | |
126 /* store pool start address and size */ | |
127 _rvf_pools[id].start_address = p_mem; | |
128 | |
129 _rvf_pools[id].pool_size = size; | |
130 | |
131 /* Initialize the pool as a big free buffer */ | |
132 hdr = (T_RVF_INTERNAL_BUF *) p_mem; | |
133 hdr->buf_size = size - sizeof(T_RVF_INTERNAL_BUF) - sizeof(UINT32); /* last 4 bytes of the pool losts*/ | |
134 hdr->header.p_prev = NULL; | |
135 RVF_SET_PREV_IN_USE(hdr); | |
136 | |
137 NEXTCHUNK(hdr)->buf_size = 0; | |
138 | |
139 ENDSIZE(hdr) = hdr->buf_size; | |
140 | |
141 | |
142 /* get the corresponding list and insert the buffer */ | |
143 list_idx = RVF_BUF_LIST_INDEX( hdr->buf_size); | |
144 hdr->p_next = lists[list_idx]; | |
145 lists[list_idx] = hdr; | |
146 | |
147 last_remainder = hdr; | |
148 | |
149 } | |
150 | |
151 void rvf_mbox_buffer_init(T_RVF_RT_ADDR_ID_DATA* pRtAddrIdElement) { | |
152 UINT8 task_num, mbox_num; | |
153 /* Initialize all mailboxes queues of all tasks*/ | |
154 for (task_num = 0; task_num < MAX_RVF_TASKS; task_num++) { | |
155 for (mbox_num = 0; mbox_num < RVF_NUM_TASK_MBOX; mbox_num++) { | |
156 pRtAddrIdElement->OSTaskQFirst[mbox_num] = NULL; | |
157 pRtAddrIdElement->OSTaskQLast[mbox_num] = NULL; | |
158 } | |
159 } | |
160 } | |
161 /******************************************************************************* | |
162 ** | |
163 ** Function _rvf_buffer_init | |
164 ** | |
165 ** Description Called once internally by rvf at startup to initialize all | |
166 ** buffers and free buffer pools. | |
167 ** | |
168 ** Returns void | |
169 ** | |
170 *******************************************************************************/ | |
171 void _rvf_buffer_init(void) | |
172 { | |
173 UINT8 list_num; | |
174 UINT16 memory_bank_num; | |
175 | |
176 /* Initialize all mailboxes queues of all tasks*/ | |
177 /* for (task_num = 0; task_num < MAX_RVF_TASKS; task_num++) | |
178 { | |
179 for (mbox_num = 0; mbox_num < RVF_NUM_TASK_MBOX; mbox_num++) | |
180 { | |
181 OSTaskQFirst[task_num][mbox_num] = NULL; | |
182 OSTaskQLast [task_num][mbox_num] = NULL; | |
183 //pRtAddrIdTable[task_num]->OSTaskQFirst[mbox_num] = NULL; // only if static | |
184 //pRtAddrIdTable[task_num]->OSTaskQLast[mbox_num] = NULL; // only if static | |
185 } | |
186 } */ | |
187 | |
188 /* initialize free lists */ | |
189 for (list_num = 0; list_num < RVF_NB_FREE_LISTS; list_num++) | |
190 { | |
191 lists[list_num] = NULL; | |
192 } | |
193 | |
194 | |
195 /* initialize buffer pools */ | |
196 _rvf_init_mem_pool(); | |
197 | |
198 /* Initialize real memory banks */ | |
199 for (memory_bank_num = 0; memory_bank_num < RVF_MAX_REAL_MB; memory_bank_num++) | |
200 { | |
201 rvf_banks[memory_bank_num].cur_memory_used = 0; | |
202 rvf_banks[memory_bank_num].watermark = 0; | |
203 rvf_banks[memory_bank_num].max = 0; | |
204 rvf_banks[memory_bank_num].first_buffer_index = RVF_INVALID_INDEX; | |
205 rvf_banks[memory_bank_num].last_buffer_index = RVF_INVALID_INDEX; | |
206 rvf_banks[memory_bank_num].func = 0; | |
207 rvf_banks[memory_bank_num].returned_red = FALSE; | |
208 #if RVF_ENABLE_STATS | |
209 rvf_banks[memory_bank_num].max_reached = 0; | |
210 rvf_banks[memory_bank_num].required_size = 0; | |
211 rvf_banks[memory_bank_num].num_buf = 0; | |
212 #endif | |
213 } | |
214 | |
215 /* Initialize total memory banks */ | |
216 for (memory_bank_num = 0; memory_bank_num < RVF_MAX_TOTAL_MB; memory_bank_num++) | |
217 { | |
218 rvf_name_id[memory_bank_num].mb_params.size = 0; | |
219 rvf_name_id[memory_bank_num].mb_params.watermark = 0; | |
220 } | |
221 | |
222 | |
223 /* initialize array of waiting buffers */ | |
224 first_free_element = 0; | |
225 for( memory_bank_num = 0; memory_bank_num < RVF_MAX_WAITING_BUF; memory_bank_num++) | |
226 { waiting_buffers[memory_bank_num] = NULL; | |
227 next_buffer[memory_bank_num] = memory_bank_num + 1; | |
228 } | |
229 next_buffer[RVF_MAX_WAITING_BUF-1] = RVF_INVALID_INDEX; | |
230 } | |
231 | |
232 /******************************************************************************* | |
233 ** | |
234 ** Function _rvf_send_msg_to_mbox | |
235 ** | |
236 ** Description Called by applications to send a buffer to a SWE. | |
237 ** (Temporary internal use - DO NOT USE IT !) | |
238 ** (Presently, only for Christophe ) | |
239 ** Returns RVF_OK if successful, else an error code. | |
240 ** | |
241 *******************************************************************************/ | |
242 T_RVF_RET _rvf_send_msg_to_mbox (T_RVF_G_ADDR_ID addr_id, UINT8 mbox,void *msg){ | |
243 return rvf_adapt_send_msg(addr_id, msg, mbox); | |
244 } | |
245 | |
246 /*T_RVF_RET _rvf_send_msg_to_mbox (T_RVF_ADDR_ID addr_id, UINT8 mbox,void *msg) | |
247 { | |
248 T_RVF_INTERNAL_BUF *p_hdr; | |
249 UINT8 task_id = (UINT8)addr_id; | |
250 | |
251 | |
252 if ((task_id >= MAX_RVF_TASKS) ) | |
253 { | |
254 rvf_send_trace( "RVF: rvf_send_msg(): invalid taskid", 35, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
255 rvf_free_buf (msg); | |
256 return RVF_INVALID_PARAMETER; | |
257 } | |
258 | |
259 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
260 | |
261 if (_rvf_chk_buf_damage(msg) == TRUE) | |
262 { rvf_send_trace( "RVF: rvf_send_msg(): buffer corrupted", 37, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
263 } | |
264 #endif | |
265 | |
266 | |
267 ((T_RV_HDR *)msg)->dest_addr_id = addr_id; | |
268 p_hdr = USER2MEM(msg); | |
269 | |
270 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
271 | |
272 if ( RVF_BUF_IS_LINKED( p_hdr) ) | |
273 { | |
274 rvf_send_trace( "RVF: rvf_send_msg(): buffer already enqueued", 44, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
275 return RVF_MEMORY_ERR; | |
276 } | |
277 #endif | |
278 | |
279 rvf_disable(8); | |
280 | |
281 | |
282 if (OSTaskQFirst[task_id][mbox]) | |
283 { OSTaskQLast[task_id][mbox]->p_next = p_hdr; | |
284 } | |
285 else | |
286 { OSTaskQFirst[task_id][mbox] = p_hdr; | |
287 } | |
288 OSTaskQLast[task_id][mbox] = p_hdr; | |
289 | |
290 p_hdr->p_next = NULL; | |
291 | |
292 if (pRtAddrIdTable[task_id]->OSTaskQFirst[mbox]) { | |
293 pRtAddrIdTable[task_id]->OSTaskQLast[mbox]->p_next = p_hdr; | |
294 } else { | |
295 pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr; | |
296 } | |
297 pRtAddrIdTable[task_id]->OSTaskQLast[mbox] = p_hdr; | |
298 | |
299 p_hdr->p_next = NULL; | |
300 | |
301 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
302 RVF_SET_BUF_LINKED(p_hdr); | |
303 #endif | |
304 | |
305 rvf_enable(); | |
306 | |
307 rvf_send_event(task_id, (UINT16) (EVENT_MASK(mbox)) ); | |
308 return RVF_OK; | |
309 }*/ | |
310 | |
311 /******************************************************************************* | |
312 ** | |
313 ** Function rvf_read_mbox | |
314 ** | |
315 ** Description Called by applications to read a buffer from one of | |
316 ** the task mailboxes. | |
317 ** | |
318 ** Returns NULL if the mailbox was empty, else the address of a buffer | |
319 ** | |
320 *******************************************************************************/ | |
321 void * rvf_read_mbox (UINT8 mbox) { | |
322 T_RVF_G_ADDR_ID task_id = rvf_get_taskid(); | |
323 | |
324 return rvf_read_addr_mbox (task_id, mbox) ; | |
325 } | |
326 void * rvf_read_addr_mbox (T_RVF_G_ADDR_ID task_id, UINT8 mbox) { | |
327 void * p_buf = NULL; | |
328 T_RVF_INTERNAL_BUF * p_hdr; | |
329 | |
330 mbox=resolveHostAddrId(mbox); | |
331 | |
332 if ((task_id >= MAX_RVF_TASKS) || (mbox >= RVF_NUM_TASK_MBOX)) | |
333 { rvf_send_trace( "RVF: rvf_read_mbox(): invalid taskid or mbox", 44, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
334 return NULL; | |
335 } | |
336 | |
337 rvf_disable(9); /* enter critical section */ | |
338 | |
339 /* if the chained list is not empty */ | |
340 /*if ( OSTaskQFirst[task_id][mbox] ) | |
341 { p_hdr = OSTaskQFirst[task_id][mbox]; | |
342 OSTaskQFirst[task_id][mbox] = p_hdr->p_next; | |
343 | |
344 p_hdr->p_next = NULL;*/ | |
345 if ( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] ) { | |
346 p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox]; | |
347 pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr->p_next; | |
348 | |
349 p_hdr->p_next = NULL; | |
350 | |
351 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
352 RVF_SET_BUF_UNLINKED(p_hdr); /* change buffer status */ | |
353 #endif | |
354 p_buf = (UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF); | |
355 } | |
356 | |
357 rvf_enable(); /* exit critical section */ | |
358 | |
359 return (p_buf); | |
360 } | |
361 | |
362 /******************************************************************************* | |
363 ** | |
364 ** Function rvf_enqueue | |
365 ** | |
366 ** Description Enqueue a buffer at the tail of the queue | |
367 ** | |
368 ** Returns RVF_OK if successful, else an error code. | |
369 ** | |
370 *******************************************************************************/ | |
371 T_RVF_RET rvf_enqueue (T_RVF_BUFFER_Q *p_q, void *p_buf) | |
372 { | |
373 T_RVF_INTERNAL_BUF *p_hdr; | |
374 | |
375 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
376 if ( _rvf_chk_buf_damage(p_buf) ) | |
377 { rvf_send_trace( "RVF: rvf_enqueue(): buffer corrupted", 36, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID); | |
378 } | |
379 #endif | |
380 | |
381 /* check if the buffer has been already enqueued */ | |
382 p_hdr = USER2MEM(p_buf); | |
383 | |
384 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
385 if( RVF_BUF_IS_LINKED(p_hdr) ) | |
386 { | |
387 rvf_send_trace( "RVF: rvf_enqueue(): buffer already enqueued", 43, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID); | |
388 return RVF_MEMORY_ERR; | |
389 } | |
390 #endif | |
391 | |
392 rvf_disable(10); /* enter critical section */ | |
393 | |
394 /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */ | |
395 /* p_q->p_last and p_q->p_first point to the user buffer, since p_hdr->p_next points to the T_RVF_INTERNAL_BUF */ | |
396 if (p_q->p_first) /* if the queue is not empty */ | |
397 { | |
398 T_RVF_INTERNAL_BUF * p_last_hdr = (T_RVF_INTERNAL_BUF *) ((UINT8 *)p_q->p_last - sizeof(T_RVF_INTERNAL_BUF) ); | |
399 p_last_hdr->p_next = p_hdr; | |
400 } | |
401 else | |
402 p_q->p_first = p_buf; | |
403 | |
404 p_q->p_last = p_buf; | |
405 p_q->count++; | |
406 | |
407 p_hdr->p_next = NULL; | |
408 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
409 RVF_SET_BUF_LINKED(p_hdr); /* change buffer status */ | |
410 #endif | |
411 | |
412 rvf_enable(); /* exit critical section */ | |
413 return RVF_OK; | |
414 } | |
415 | |
416 | |
417 | |
418 /******************************************************************************* | |
419 ** | |
420 ** Function rvf_dequeue | |
421 ** | |
422 ** Description Dequeue a buffer from the head of a queue | |
423 ** | |
424 ** Returns NULL if queue is empty, else buffer | |
425 ** | |
426 *******************************************************************************/ | |
427 void * rvf_dequeue (T_RVF_BUFFER_Q *p_q) | |
428 { | |
429 T_RVF_INTERNAL_BUF *p_hdr; | |
430 | |
431 if (!p_q->count) /* if the queue is empty */ | |
432 return (NULL); | |
433 | |
434 rvf_disable(12); /* enter critical section */ | |
435 | |
436 p_hdr = USER2MEM(p_q->p_first ); | |
437 | |
438 | |
439 /* Keep buffers such that RVF header is invisible */ | |
440 if (p_hdr->p_next) | |
441 p_q->p_first = ((UINT8 *)p_hdr->p_next + sizeof(T_RVF_INTERNAL_BUF)); | |
442 else | |
443 { | |
444 p_q->p_first = NULL; | |
445 p_q->p_last = NULL; | |
446 } | |
447 | |
448 p_q->count--; | |
449 | |
450 p_hdr->p_next = NULL; | |
451 | |
452 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
453 RVF_SET_BUF_UNLINKED(p_hdr); /* change buffer status */ | |
454 #endif | |
455 | |
456 rvf_enable(); /* exit critical section */ | |
457 | |
458 return (MEM2USER(p_hdr) ); | |
459 } | |
460 | |
461 | |
462 | |
463 /******************************************************************************* | |
464 ** | |
465 ** Function rvf_enqueue_head | |
466 ** | |
467 ** Description Enqueue a buffer at the head of the queue | |
468 ** | |
469 ** Returns RVF_OK if successful, else an error code. | |
470 ** | |
471 *******************************************************************************/ | |
472 T_RVF_RET rvf_enqueue_head (T_RVF_BUFFER_Q *p_q, void *p_buf) | |
473 { | |
474 T_RVF_INTERNAL_BUF *p_hdr; | |
475 | |
476 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
477 if ( _rvf_chk_buf_damage(p_buf) ) | |
478 { rvf_send_trace( "RVF: rvf_enqueue_head(): buffer corrupted", 41, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
479 } | |
480 #endif | |
481 | |
482 p_hdr = USER2MEM(p_buf); | |
483 | |
484 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
485 if( RVF_BUF_IS_LINKED(p_hdr) ) | |
486 { rvf_send_trace( "RVF: rvf_enqueue_head(): buffer already enqueued", 48, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
487 return RVF_MEMORY_ERR; | |
488 } | |
489 #endif | |
490 | |
491 rvf_disable(11); /* enter critical section */ | |
492 | |
493 if (p_q->p_first) /* if the queue is not empty */ | |
494 { p_hdr->p_next = (T_RVF_INTERNAL_BUF *)((UINT8 *)p_q->p_first - sizeof(T_RVF_INTERNAL_BUF) ); | |
495 p_q->p_first = p_buf; | |
496 } | |
497 else | |
498 { p_q->p_first = p_buf; | |
499 p_q->p_last = p_buf; | |
500 p_hdr->p_next = NULL; | |
501 } | |
502 p_q->count++; | |
503 | |
504 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
505 RVF_SET_BUF_LINKED(p_hdr); /* change buffer status */ | |
506 #endif | |
507 | |
508 | |
509 rvf_enable(); /* exit critical section */ | |
510 | |
511 return RVF_OK; | |
512 } | |
513 | |
514 | |
515 | |
516 /******************************************************************************* | |
517 ** | |
518 ** Function rvf_get_buf_size | |
519 ** | |
520 ** Description Called by an application to get the size of a buffer. | |
521 ** | |
522 ** Returns the size of the buffer or 0 if the address is invalid. | |
523 ** | |
524 *******************************************************************************/ | |
525 INLINE UINT32 rvf_get_buf_size (void *bptr) | |
526 { | |
527 T_RVF_INTERNAL_BUF *p_hdr; | |
528 | |
529 p_hdr = (T_RVF_INTERNAL_BUF *)((UINT8 *) bptr - sizeof(T_RVF_INTERNAL_BUF) ); | |
530 | |
531 if ((UINT32)p_hdr & 1) return 0; /* invalid pointer: odd address*/ | |
532 | |
533 return (GETSIZE(p_hdr) - RVF_CORRUPT_OVERHEAD) ; | |
534 } | |
535 | |
536 | |
537 /******************************************************************************* | |
538 ** | |
539 ** Function _rvf_chk_buf_damage | |
540 ** | |
541 ** Description Called internally by rvf to check for buffer corruption. | |
542 ** | |
543 ** Returns TRUE if there is a problem, else FALSE | |
544 ** | |
545 *******************************************************************************/ | |
546 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
547 BOOLEAN _rvf_chk_buf_damage(void *bptr) | |
548 { | |
549 UINT32 *lg; | |
550 T_RVF_INTERNAL_BUF * p_hdr; | |
551 | |
552 if((UINT32)bptr & 1) /* odd address */ | |
553 { return TRUE; | |
554 } | |
555 | |
556 p_hdr = USER2MEM(bptr); /* get the internal header */ | |
557 | |
558 lg = (UINT32*)( (UINT8*)bptr + GETSIZE(p_hdr) - sizeof(UINT32) ); | |
559 | |
560 if (lg == 0) | |
561 return TRUE; | |
562 | |
563 if(*lg == GETSIZE(p_hdr) ) | |
564 { | |
565 return FALSE; | |
566 } | |
567 return TRUE; | |
568 } | |
569 #endif | |
570 | |
571 | |
572 | |
573 /******************************************************************************* | |
574 ** | |
575 ** Function _find_buf | |
576 ** | |
577 ** Description Internal function which is in charge of finding a free buffer | |
578 ** of the requested size in one of the lists. | |
579 ** | |
580 ** Returns A pointer to the buffer header, or NULL if none available | |
581 ** | |
582 *******************************************************************************/ | |
583 INLINE void * _find_buf (UINT32 size) | |
584 { | |
585 T_RVF_INTERNAL_BUF * p_hdr; | |
586 UINT8 idx; | |
587 | |
588 if (size == 0) /* if user requires a 0 byte buffer !! */ | |
589 { return (NULL); | |
590 } | |
591 | |
592 /* add the overhead for buffer corruption check */ | |
593 size = REQ2SIZE(size); | |
594 | |
595 /* find the corresponding list */ | |
596 idx = RVF_BUF_LIST_INDEX(size); | |
597 | |
598 /* 1. try in the bin corresponding to the requested size. */ | |
599 /* 2. try to use the last_remainder chunk. */ | |
600 /* 3. try in the others bins of greater size. */ | |
601 | |
602 if( (lists[idx] == NULL) || ( GETSIZE(lists[idx]) < size) ) | |
603 /* if the first buffer in the appropriate bin is not big enough. */ | |
604 { | |
605 rvf_disable(4); /* enter critical section */ | |
606 | |
607 if( last_remainder != NULL) | |
608 { | |
609 p_hdr = last_remainder; | |
610 | |
611 /* if the last remainder is big enough */ | |
612 if( GETSIZE(p_hdr) >= size ) | |
613 { | |
614 | |
615 if( GETSIZE(p_hdr) >= (size + RVF_MIN_USABLE_SIZE ) ) /* if the free part may be used */ | |
616 { /* create a new free buffer and link it in the appropriate list*/ | |
617 | |
618 T_RVF_INTERNAL_BUF * new_buf; | |
619 UINT8 new_idx; | |
620 | |
621 new_buf = (T_RVF_INTERNAL_BUF *) ((UINT8*)p_hdr + size + sizeof(T_RVF_INTERNAL_BUF)); | |
622 new_buf->buf_size = GETSIZE(p_hdr) - size - sizeof(T_RVF_INTERNAL_BUF); | |
623 ENDSIZE(new_buf) = new_buf->buf_size; | |
624 | |
625 /* remove the used buffer from the list */ | |
626 if( p_hdr->header.p_prev != NULL) | |
627 { (p_hdr->header.p_prev)->p_next = p_hdr->p_next; | |
628 } | |
629 else | |
630 { lists[ RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) )] = p_hdr->p_next; | |
631 } | |
632 if( p_hdr->p_next != NULL) | |
633 { (p_hdr->p_next)->header.p_prev = p_hdr->header.p_prev; | |
634 } | |
635 p_hdr->p_next = NULL; | |
636 | |
637 SETSIZE(p_hdr, size); | |
638 ENDSIZE(p_hdr) = size; /* to CHANGE */ | |
639 | |
640 /* insert the new buffer in the appropriate list */ | |
641 new_idx = RVF_BUF_LIST_INDEX(new_buf->buf_size); | |
642 new_buf->p_next = lists[new_idx]; | |
643 lists[new_idx] = new_buf; | |
644 new_buf->header.p_prev = NULL; | |
645 if( new_buf->p_next != NULL) | |
646 { (new_buf->p_next)->header.p_prev = new_buf; | |
647 } | |
648 RVF_SET_PREV_IN_USE(new_buf); | |
649 | |
650 last_remainder = new_buf; | |
651 | |
652 rvf_enable(); /* exit critical section */ | |
653 return p_hdr; | |
654 | |
655 } | |
656 else /* return the entire buffer */ | |
657 { | |
658 /* remove the used buffer from the list */ | |
659 if( p_hdr->header.p_prev != NULL) | |
660 { (p_hdr->header.p_prev)->p_next = p_hdr->p_next; | |
661 } | |
662 else | |
663 { lists[ RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) )] = p_hdr->p_next; | |
664 } | |
665 if( p_hdr->p_next != NULL) | |
666 { (p_hdr->p_next)->header.p_prev = p_hdr->header.p_prev; | |
667 } | |
668 p_hdr->p_next = NULL; | |
669 | |
670 RVF_SET_PREV_IN_USE( NEXTCHUNK(p_hdr) ); | |
671 | |
672 last_remainder = NULL; | |
673 | |
674 rvf_enable(); /* exit critical section */ | |
675 return p_hdr; | |
676 } | |
677 } | |
678 else /* the last remainder is too small */ | |
679 { | |
680 /* clear the last remainder */ | |
681 last_remainder = NULL; | |
682 } | |
683 | |
684 } | |
685 rvf_enable(); /* exit critical section */ | |
686 } | |
687 | |
688 while( idx < RVF_NB_FREE_LISTS ) | |
689 { | |
690 rvf_disable(4); /* enter critical section */ | |
691 | |
692 if( lists[idx] != NULL ) /*if the list is not empty */ | |
693 { /* remove the first buffer from the list */ | |
694 | |
695 p_hdr = lists[idx]; | |
696 if( GETSIZE(p_hdr) >= size) | |
697 { | |
698 if( GETSIZE(p_hdr) >= (size + RVF_MIN_USABLE_SIZE ) ) /* if the free part may be used */ | |
699 { /* create a new free buffer and link it in the appropriate list*/ | |
700 | |
701 T_RVF_INTERNAL_BUF * new_buf; | |
702 UINT8 new_idx; | |
703 | |
704 new_buf = (T_RVF_INTERNAL_BUF *) ((UINT8*)p_hdr + size + sizeof(T_RVF_INTERNAL_BUF)); | |
705 new_buf->buf_size = GETSIZE( p_hdr) - size - sizeof(T_RVF_INTERNAL_BUF); | |
706 ENDSIZE(new_buf) = new_buf->buf_size; | |
707 | |
708 /* remove the used buffer from the list */ | |
709 lists[idx] = p_hdr->p_next; | |
710 if( p_hdr->p_next != NULL) | |
711 { (p_hdr->p_next)->header.p_prev = NULL; | |
712 } | |
713 p_hdr->p_next = NULL; | |
714 | |
715 SETSIZE(p_hdr, size); | |
716 ENDSIZE(p_hdr) = size; | |
717 | |
718 /* insert the new buffer in the appropriate list */ | |
719 new_idx = RVF_BUF_LIST_INDEX(new_buf->buf_size); | |
720 new_buf->p_next = lists[new_idx]; | |
721 lists[new_idx] = new_buf; | |
722 new_buf->header.p_prev = NULL; | |
723 if( new_buf->p_next != NULL) | |
724 { (new_buf->p_next)->header.p_prev = new_buf; | |
725 } | |
726 RVF_SET_PREV_IN_USE(new_buf); | |
727 | |
728 last_remainder = new_buf; /* set this new buffer as the last remainder */ | |
729 | |
730 rvf_enable(); /* exit critical section */ | |
731 return p_hdr; | |
732 | |
733 } | |
734 else /* return the entire buffer */ | |
735 { lists[idx] = p_hdr->p_next; | |
736 if( p_hdr->p_next != NULL) | |
737 { (p_hdr->p_next)->header.p_prev = NULL; | |
738 } | |
739 p_hdr->p_next = NULL; | |
740 RVF_SET_PREV_IN_USE( NEXTCHUNK(p_hdr) ); | |
741 | |
742 if( last_remainder == p_hdr) /* if it was the last_remainder, clear it. */ | |
743 { | |
744 last_remainder = NULL; | |
745 } | |
746 | |
747 rvf_enable(); /* exit critical section */ | |
748 return p_hdr; | |
749 } | |
750 } | |
751 } | |
752 | |
753 rvf_enable(); /* exit critical section */ | |
754 | |
755 idx++; /* search in the next list */ | |
756 } | |
757 | |
758 return NULL; | |
759 } | |
760 | |
761 | |
762 /******************************************************************************* | |
763 ** | |
764 ** Function _release_buf | |
765 ** | |
766 ** Description Internal function called to release a buffer after use. | |
767 ** The parameter points to the beginning of the header. | |
768 ** | |
769 ** Returns BOOLEAN: TRUE if successful, else FALSE | |
770 ** | |
771 *******************************************************************************/ | |
772 INLINE BOOLEAN _release_buf (T_RVF_INTERNAL_BUF *p_hdr) | |
773 { UINT8 idx; | |
774 | |
775 #if RVF_ENABLE_BUF_CORRUPTION_CHECK /* check for buffer corruption:i.e. if user wrote data after the end of the buffer */ | |
776 if ( _rvf_chk_buf_damage( MEM2USER(p_hdr) ) ) | |
777 { rvf_send_trace( "RVF: _release_buf(): buffer corrupted", 37, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
778 return FALSE; | |
779 } | |
780 | |
781 /* check if the buffer has been already freed */ | |
782 if ( RVF_IS_PREV_FREE( NEXTCHUNK(p_hdr) ) ) /* check buffer status */ | |
783 { rvf_send_trace( "RVF: _release_buf(): buffer already freed", 41, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
784 return FALSE; | |
785 } | |
786 | |
787 #endif | |
788 | |
789 #if RVF_ENABLE_BUF_LINKAGE_CHECK /* check for buffer linkage */ | |
790 if ( RVF_BUF_IS_LINKED(p_hdr) ) /* check buffer status */ | |
791 { rvf_send_trace( "RVF: _release_buf(): free buf buffer linked", 43, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
792 return FALSE; | |
793 } | |
794 #endif | |
795 | |
796 | |
797 rvf_disable(6); /* enter critical section */ | |
798 | |
799 /* try to coalesce the buffer with its neighbors (left and right) */ | |
800 | |
801 if( RVF_IS_PREV_FREE(p_hdr) ) | |
802 { /* merge the buffer with its left neighbor */ | |
803 UINT32 left_buf_size = *((UINT32*)((UINT8*)p_hdr - sizeof(UINT32) ) ); | |
804 T_RVF_INTERNAL_BUF * left_buf = (T_RVF_INTERNAL_BUF *) ((UINT8 *)p_hdr - left_buf_size - sizeof(T_RVF_INTERNAL_BUF) ); | |
805 | |
806 /* remove the left buffer from its list */ | |
807 if( left_buf->header.p_prev == NULL) | |
808 { lists[ RVF_BUF_LIST_INDEX(left_buf_size)] = left_buf->p_next; | |
809 } | |
810 else | |
811 { (left_buf->header.p_prev)->p_next = left_buf->p_next; | |
812 } | |
813 if( left_buf->p_next != NULL) | |
814 { | |
815 (left_buf->p_next)->header.p_prev = left_buf->header.p_prev; | |
816 } | |
817 /* set the size of the newly created buffer */ | |
818 SETSIZE(left_buf, (left_buf_size + GETSIZE(p_hdr) + sizeof(T_RVF_INTERNAL_BUF) ) ); | |
819 /* set the current buffer as free to allow check for double free */ | |
820 RVF_SET_PREV_FREE( NEXTCHUNK(p_hdr) ); | |
821 | |
822 p_hdr = left_buf; | |
823 } | |
824 | |
825 /* check for pool limits */ | |
826 if( GETSIZE( NEXTCHUNK(p_hdr) ) != 0) | |
827 { T_RVF_INTERNAL_BUF * right_buf = NEXTCHUNK(p_hdr); | |
828 /* merge the buffer with its right neighbor */ | |
829 | |
830 if( RVF_IS_PREV_FREE( NEXTCHUNK(right_buf) ) ) | |
831 { /* remove the right buffer from its list */ | |
832 UINT32 right_buf_size = GETSIZE( right_buf); | |
833 | |
834 if( right_buf->header.p_prev == NULL) | |
835 { lists[ RVF_BUF_LIST_INDEX(right_buf_size)] = right_buf->p_next; | |
836 } | |
837 else | |
838 { (right_buf->header.p_prev)->p_next = right_buf->p_next; | |
839 } | |
840 if( right_buf->p_next != NULL) | |
841 { (right_buf->p_next)->header.p_prev = right_buf->header.p_prev; | |
842 } | |
843 | |
844 right_buf_size += GETSIZE(p_hdr); | |
845 SETSIZE(p_hdr, (right_buf_size + sizeof(T_RVF_INTERNAL_BUF) ) ); | |
846 | |
847 if( last_remainder == right_buf) /* keep as last_remainder */ | |
848 { last_remainder = p_hdr; | |
849 } | |
850 } | |
851 } | |
852 | |
853 /* enqueue the free buffer in the appropriate list */ | |
854 idx = RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) ); | |
855 p_hdr->header.p_prev = NULL; | |
856 p_hdr->p_next = lists[idx]; | |
857 lists[idx] = p_hdr; | |
858 if( p_hdr->p_next != NULL) | |
859 { (p_hdr->p_next)->header.p_prev = p_hdr; | |
860 } | |
861 | |
862 ENDSIZE(p_hdr) = GETSIZE(p_hdr); | |
863 RVF_SET_PREV_FREE( NEXTCHUNK(p_hdr) ); | |
864 | |
865 rvf_enable(); /* exit critical section */ | |
866 return TRUE; | |
867 } | |
868 | |
869 | |
870 /******************************************************************************* | |
871 ** Function _str_cmp | |
872 ** | |
873 ** Description Internal function which compares two null-terminated string. | |
874 ** Returns TRUE if they are equal, else FALSE. | |
875 *******************************************************************************/ | |
876 BOOLEAN _str_cmp( char *str1, char * str2) | |
877 { UINT8 i; | |
878 for ( i = 0; (str1[i] == str2[i]) && (str1[i] != 0) && (str2[i] != 0) && (i < RVF_MAX_MB_LEN); i++ ); | |
879 if ( i == RVF_MAX_MB_LEN) | |
880 { return TRUE; | |
881 } | |
882 | |
883 if ( (str1[i] == 0) && (str2[i] == 0) ) | |
884 { return TRUE; | |
885 } | |
886 return FALSE; | |
887 } | |
888 | |
889 /****************************************************************************** | |
890 ** | |
891 ** MEMORY BANK RELATED FUNCTIONS | |
892 ** | |
893 ******************************************************************************/ | |
894 | |
895 /******************************************************************************* | |
896 ** | |
897 ** Function _remove_from_list | |
898 ** | |
899 ** Description Internal function called to remove a buffer from the list of | |
900 ** buffer waiting to be counted on the memory bank. | |
901 ** The parameter points to the beginning of the header. | |
902 ** | |
903 ** Returns BOOLEAN: TRUE if successful, else FALSE | |
904 ** | |
905 *******************************************************************************/ | |
906 BOOLEAN _remove_from_list (void *bptr, T_RVF_MB * mb) | |
907 { UINT16 * index; | |
908 UINT16 free_elem, prec; | |
909 | |
910 /* check all elements of the list */ | |
911 index = &(mb->first_buffer_index); | |
912 prec = RVF_INVALID_INDEX; | |
913 | |
914 while ( (*index != RVF_INVALID_INDEX) && (waiting_buffers[*index]!=bptr) ) | |
915 { prec = *index; | |
916 index = &(next_buffer[*index]); | |
917 } | |
918 | |
919 if (waiting_buffers[*index] == bptr) | |
920 { free_elem = *index; | |
921 *index = next_buffer[free_elem]; /* link preceding element to the next one */ | |
922 | |
923 if (next_buffer[free_elem] == RVF_INVALID_INDEX ) /* last element in the list */ | |
924 { mb->last_buffer_index = prec; | |
925 } | |
926 | |
927 waiting_buffers[free_elem] = NULL; | |
928 next_buffer[free_elem] = first_free_element; /* link free elements */ | |
929 first_free_element = free_elem; | |
930 return TRUE; | |
931 } | |
932 return FALSE; /* buffer not found */ | |
933 } | |
934 | |
935 | |
936 /******************************************************************************* | |
937 ** | |
938 ** Function _add_to_list | |
939 ** | |
940 ** Description Internal function called to add a buffer to the list of | |
941 ** buffer waiting to be counted on the memory bank. | |
942 ** The parameter points to the beginning of the header. | |
943 ** | |
944 ** Returns BOOLEAN: TRUE if successful, else FALSE | |
945 ** | |
946 *******************************************************************************/ | |
947 BOOLEAN _add_to_list (void *bptr, T_RVF_MB * mb) | |
948 { UINT16 index = first_free_element; | |
949 | |
950 first_free_element = next_buffer[index]; | |
951 | |
952 waiting_buffers[index] = bptr; | |
953 next_buffer[index] = RVF_INVALID_INDEX; | |
954 | |
955 if ( mb->last_buffer_index == RVF_INVALID_INDEX) /* empty list */ | |
956 { mb->first_buffer_index = index; | |
957 mb->last_buffer_index = index; | |
958 } | |
959 else | |
960 { next_buffer[mb->last_buffer_index] = index; | |
961 mb->last_buffer_index = index; | |
962 } | |
963 | |
964 return TRUE; | |
965 } | |
966 | |
967 | |
968 /******************************************************************************* | |
969 ** | |
970 ** Function rvf_create_mb | |
971 ** | |
972 ** Description Called by an application to create a memory bank | |
973 ** | |
974 ** Parameters: memory bank name, memory bank param | |
975 ** (return) memory bank id | |
976 ** | |
977 ** Returns T_RVF_RET: RVF_OK if success | |
978 ** | |
979 *******************************************************************************/ | |
980 T_RVF_RET rvf_create_mb(T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM mb_param, T_RVF_MB_ID *mb_id) | |
981 { UINT8 num_mb; | |
982 T_RVF_MB * mb; | |
983 UINT32 available_mem = 0; | |
984 UINT32 required_mem = 0; | |
985 | |
986 /* find the mb name in the array */ | |
987 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
988 | |
989 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
990 { | |
991 /* DLC added for dynamic memory bank creation*/ | |
992 | |
993 /* search the first available place in the array */ | |
994 T_RVF_MB_ID first_available_mb_id = 0; | |
995 BOOLEAN mb_id_found = FALSE; | |
996 | |
997 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (rvf_name_id[num_mb].mb_name[0] != 0) ; num_mb++) | |
998 { if( rvf_name_id[num_mb].mb_id == first_available_mb_id) | |
999 { first_available_mb_id ++; | |
1000 } | |
1001 } | |
1002 | |
1003 while( (first_available_mb_id < RVF_MAX_REAL_MB) && (mb_id_found == FALSE) ) | |
1004 { | |
1005 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (rvf_name_id[num_mb].mb_name[0] != 0) && (rvf_name_id[num_mb].mb_id != first_available_mb_id) ; num_mb++); | |
1006 if ( rvf_name_id[num_mb].mb_id != first_available_mb_id) | |
1007 { /* available mb id found */ | |
1008 mb_id_found = TRUE; | |
1009 } | |
1010 else | |
1011 { /* try the next one */ | |
1012 first_available_mb_id++; | |
1013 } | |
1014 } | |
1015 | |
1016 if ( (num_mb == RVF_MAX_TOTAL_MB) || (first_available_mb_id + 1 >= RVF_MAX_REAL_MB ) ) /* no available space in the array */ | |
1017 | |
1018 { *mb_id = RVF_INVALID_MB_ID; | |
1019 return RVF_INVALID_PARAMETER; | |
1020 } | |
1021 | |
1022 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_disable(20); /* enter critical section */ | |
1023 | |
1024 /* create the new mb name and id */ | |
1025 strcpy( rvf_name_id[num_mb].mb_name, mb_name); | |
1026 rvf_name_id[num_mb].mb_id = first_available_mb_id; | |
1027 | |
1028 /* initialize the next one */ | |
1029 rvf_name_id[num_mb+1].mb_name[0] = 0; | |
1030 rvf_name_id[num_mb+1].mb_id = 0; | |
1031 | |
1032 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_enable(); /* exit critical section */ | |
1033 } | |
1034 | |
1035 /* check if the memory bank has been already created */ | |
1036 if ( rvf_name_id[ num_mb].mb_params.size != 0) | |
1037 { *mb_id = RVF_INVALID_MB_ID; | |
1038 return RVF_INTERNAL_ERR; | |
1039 } | |
1040 | |
1041 rvf_get_available_mem( &available_mem, &required_mem); | |
1042 | |
1043 if ( ( (required_mem + mb_param.size)*100) > ( available_mem * _rvf_get_mem_usage_ratio()) ) /* if there is not enough available memory to create this mb */ | |
1044 { *mb_id = RVF_INVALID_MB_ID; /* In a next version: try to create a dynamic pool */ | |
1045 return RVF_MEMORY_ERR; | |
1046 } | |
1047 | |
1048 rvf_disable(20); /* enter critical section */ | |
1049 | |
1050 /* save the mb parameters for deletion */ | |
1051 rvf_name_id[num_mb].mb_params.size = mb_param.size; | |
1052 rvf_name_id[num_mb].mb_params.watermark = mb_param.watermark; | |
1053 | |
1054 * mb_id = rvf_name_id[num_mb].mb_id; | |
1055 mb = &rvf_banks[ *mb_id ]; | |
1056 /* initialize the memory bank structure */ | |
1057 mb->watermark += mb_param.watermark; | |
1058 mb->max += mb_param.size; | |
1059 | |
1060 rvf_enable(); /* exit critical section */ | |
1061 | |
1062 return RVF_OK; | |
1063 } | |
1064 | |
1065 | |
1066 /******************************************************************************* | |
1067 ** | |
1068 ** Function rvf_get_mb_id | |
1069 ** | |
1070 ** Description Called by an application to get the memory bank id from its name | |
1071 ** | |
1072 ** Parameters: memory bank name | |
1073 ** (return) memory bank id | |
1074 ** | |
1075 ** Returns T_RVF_RET: RVF_OK if success | |
1076 ** | |
1077 *******************************************************************************/ | |
1078 T_RVF_RET rvf_get_mb_id(T_RVF_MB_NAME mb_name, T_RVF_MB_ID *mb_id) | |
1079 { UINT8 num_mb; | |
1080 | |
1081 | |
1082 /* find the mb name in the array */ | |
1083 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1084 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1085 { *mb_id = RVF_INVALID_MB_ID; | |
1086 return RVF_INVALID_PARAMETER; | |
1087 } | |
1088 if ( rvf_banks[ rvf_name_id[num_mb].mb_id ].max == 0 ) | |
1089 { /* the memory bank has not been created */ | |
1090 *mb_id = RVF_INVALID_MB_ID; | |
1091 return RVF_NOT_READY; | |
1092 } | |
1093 *mb_id = rvf_name_id[num_mb].mb_id; | |
1094 return RVF_OK; | |
1095 } | |
1096 | |
1097 | |
1098 /******************************************************************************* | |
1099 ** | |
1100 ** Function rvf_delete_mb | |
1101 ** | |
1102 ** Description Called by an application to delete a memory bank | |
1103 ** | |
1104 ** Parameters: memory bank name | |
1105 ** | |
1106 ** Returns T_RVF_RET: RVF_OK if success | |
1107 ** | |
1108 *******************************************************************************/ | |
1109 T_RVF_RET rvf_delete_mb(T_RVF_MB_NAME mb_name) | |
1110 { UINT8 num_mb; | |
1111 T_RVF_MB * mb; | |
1112 | |
1113 /* find the mb name in the array */ | |
1114 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1115 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1116 { return RVF_INVALID_PARAMETER; | |
1117 } | |
1118 mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1119 | |
1120 /* check if the mb is used more than once or not */ | |
1121 if ( mb->max == rvf_name_id[num_mb].mb_params.size ) | |
1122 { /* mb is used only once, check if cur_memory_used > 0 */ | |
1123 if ( mb->cur_memory_used > 0) | |
1124 { rvf_send_trace( "RVF: rvf_delete_mb(): not all buffers have been freed", 53, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
1125 return RVF_MEMORY_ERR; | |
1126 /* free all buffers ????? -> NOT POSSIBLE */ | |
1127 } | |
1128 /* initialize mb params */ | |
1129 mb->max = 0; | |
1130 mb->first_buffer_index = RVF_INVALID_INDEX; | |
1131 mb->last_buffer_index = RVF_INVALID_INDEX; | |
1132 mb->watermark = 0; | |
1133 mb->returned_red = FALSE; | |
1134 mb->func = 0; | |
1135 #if RVF_ENABLE_STATS | |
1136 mb->max_reached = 0; | |
1137 mb->required_size = 0; | |
1138 mb->num_buf = 0; | |
1139 #endif | |
1140 | |
1141 } | |
1142 else /* mb is still used by another entity */ | |
1143 { /* change mb params */ | |
1144 mb->max -= rvf_name_id[num_mb].mb_params.size; | |
1145 mb->watermark -= rvf_name_id[num_mb].mb_params.watermark; | |
1146 } | |
1147 | |
1148 rvf_name_id[num_mb].mb_params.size = 0; | |
1149 rvf_name_id[num_mb].mb_params.watermark = 0; | |
1150 | |
1151 return RVF_OK; | |
1152 } | |
1153 | |
1154 T_RVF_RET rvf_mb_is_used(T_RVF_MB_NAME mb_name, UINT8* isUsed) { | |
1155 UINT8 num_mb; | |
1156 T_RVF_MB * mb; | |
1157 | |
1158 *isUsed=0; | |
1159 | |
1160 /* find the mb name in the array */ | |
1161 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1162 if ( num_mb == RVF_MAX_TOTAL_MB ) {/* mb name not found */ | |
1163 return RVF_INVALID_PARAMETER; | |
1164 } | |
1165 mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1166 | |
1167 /* check if the mb is used more than once or not */ | |
1168 if ( mb->max == rvf_name_id[num_mb].mb_params.size ) { | |
1169 /* mb is used only once, check if cur_memory_used > 0 */ | |
1170 if ( mb->cur_memory_used > 0) *isUsed=1; | |
1171 } | |
1172 return RVF_OK; | |
1173 } | |
1174 | |
1175 | |
1176 | |
1177 /******************************************************************************* | |
1178 ** | |
1179 ** Function rvf_get_mb_status | |
1180 ** | |
1181 ** Description Called by an application to get the status of a memory bank | |
1182 ** | |
1183 ** Parameters: memory bank id | |
1184 ** | |
1185 ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok, | |
1186 ** RVF_YELLOW if watermark limit has been reached, | |
1187 ** RVF_RED if max size has been reached | |
1188 ** | |
1189 *******************************************************************************/ | |
1190 T_RVF_MB_STATUS rvf_get_mb_status(T_RVF_MB_ID mb_id) | |
1191 { T_RVF_MB * mb; | |
1192 | |
1193 /* checking for invalid memory bank IDs */ | |
1194 if (mb_id >= RVF_MAX_REAL_MB) | |
1195 { | |
1196 #ifdef RVM_DAR_SWE | |
1197 dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR, | |
1198 DAR_ASCII_FORMAT, | |
1199 RVM_USE_ID); | |
1200 #else | |
1201 rvf_send_trace (RVF_INVALID_MD_ID_ERRROR, | |
1202 sizeof (RVF_INVALID_MD_ID_ERRROR) - 1, | |
1203 NULL_PARAM, | |
1204 RV_TRACE_LEVEL_ERROR, | |
1205 RVM_USE_ID); | |
1206 #endif | |
1207 return RVF_RED; | |
1208 } | |
1209 mb = &rvf_banks[mb_id]; | |
1210 | |
1211 if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */ | |
1212 { return RVF_RED; | |
1213 } | |
1214 | |
1215 if ( mb->cur_memory_used < mb->watermark ) | |
1216 { return RVF_GREEN; | |
1217 } | |
1218 else | |
1219 { if ( mb->cur_memory_used < mb->max ) | |
1220 { return RVF_YELLOW; | |
1221 } | |
1222 else | |
1223 { return RVF_RED; /* since max and cur_memory_used are set to 0 for not-created mb, it will return RED*/ | |
1224 } | |
1225 } | |
1226 } | |
1227 | |
1228 /******************************************************************************* | |
1229 ** | |
1230 ** Function rvf_get_mb_unused_mem | |
1231 ** | |
1232 ** Description Called by an application to get the number of bytes available | |
1233 ** until the memory bank size. | |
1234 ** | |
1235 ** Parameters: memory bank id | |
1236 ** | |
1237 ** Returns UINT32: number of bytes available | |
1238 ** returns 0 if the memory bank has not been created. | |
1239 ** | |
1240 *******************************************************************************/ | |
1241 UINT32 rvf_get_mb_unused_mem(T_RVF_MB_ID mb_id) | |
1242 { T_RVF_MB * mb; | |
1243 mb = &rvf_banks[mb_id]; | |
1244 | |
1245 if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */ | |
1246 { return 0; | |
1247 } | |
1248 | |
1249 return( mb->max - mb->cur_memory_used); | |
1250 } | |
1251 | |
1252 /******************************************************************************* | |
1253 ** | |
1254 ** Function rvf_get_mb_unused_green_mem | |
1255 ** | |
1256 ** Description Called by an application to get the number of bytes available | |
1257 ** until the memory bank watermark. | |
1258 ** | |
1259 ** Parameters: memory bank id | |
1260 ** | |
1261 ** Returns UINT32: number of bytes available | |
1262 ** returns 0 if the memory bank has not been created. | |
1263 ** | |
1264 *******************************************************************************/ | |
1265 UINT32 rvf_get_mb_unused_green_mem(T_RVF_MB_ID mb_id) | |
1266 { T_RVF_MB * mb; | |
1267 mb = &rvf_banks[mb_id]; | |
1268 | |
1269 if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */ | |
1270 { return 0; | |
1271 } | |
1272 | |
1273 if( mb->cur_memory_used > mb->watermark) | |
1274 { return 0; | |
1275 } | |
1276 | |
1277 return( mb->watermark - mb->cur_memory_used); | |
1278 } | |
1279 | |
1280 /******************************************************************************* | |
1281 ** | |
1282 ** Function rvf_get_buf | |
1283 ** | |
1284 ** Description Called by an application to get a buffer from a memory bank | |
1285 ** | |
1286 ** Parameters: memory bank id, buffer size | |
1287 ** (return) buffer pointer to the allocated buffer or null if | |
1288 ** mb status is RVF_RED | |
1289 ** | |
1290 ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok, | |
1291 ** RVF_YELLOW if watermark limit has been reached, | |
1292 ** RVF_RED if max size has been reached (does not return a buffer) | |
1293 ** | |
1294 *******************************************************************************/ | |
1295 T_RVF_MB_STATUS rvf_get_buf(T_RVF_MB_ID mb_id, UINT32 buffer_size, T_RVF_BUFFER** p_buffer) | |
1296 { T_RVF_MB * mb; | |
1297 | |
1298 /* checking for invalid memory bank IDs */ | |
1299 if (mb_id >= RVF_MAX_REAL_MB) | |
1300 { | |
1301 #ifdef RVM_DAR_SWE | |
1302 dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR, | |
1303 DAR_ASCII_FORMAT, | |
1304 RVM_USE_ID); | |
1305 #else | |
1306 rvf_send_trace (RVF_INVALID_MD_ID_ERRROR, | |
1307 sizeof (RVF_INVALID_MD_ID_ERRROR) - 1, | |
1308 NULL_PARAM, | |
1309 RV_TRACE_LEVEL_ERROR, | |
1310 RVM_USE_ID); | |
1311 #endif | |
1312 return RVF_RED; | |
1313 } | |
1314 mb = &rvf_banks[ mb_id ]; | |
1315 | |
1316 /* check memory usage */ | |
1317 if ( ( mb->cur_memory_used + buffer_size) > mb->max ) | |
1318 { /* over the limits, return RED and do not allocate a buffer */ | |
1319 mb->returned_red = TRUE; | |
1320 *p_buffer = NULL; | |
1321 return RVF_RED; | |
1322 } | |
1323 | |
1324 /* find a buffer of the requested size */ | |
1325 *p_buffer = _find_buf( buffer_size ); | |
1326 if ( *p_buffer == NULL ) /* error during allocation, not enough memory */ | |
1327 { //rvf_send_trace( "RVF: rvf_get_buf(): not enough available physical memory", 56, NULL_PARAM, RV_TRACE_LEVEL_ERROR, TRACE_RVF_BUFFER ); | |
1328 mb->returned_red = TRUE; | |
1329 return RVF_RED; | |
1330 } | |
1331 | |
1332 #if RVF_ENABLE_STATS | |
1333 required_size += buffer_size; | |
1334 obtained_size += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)); | |
1335 used_size += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)) + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD; | |
1336 mem_in_use += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)) + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD; | |
1337 #endif | |
1338 | |
1339 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_disable(20); /* enter critical section */ | |
1340 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
1341 /* set as unlinked */ | |
1342 RVF_SET_BUF_UNLINKED((T_RVF_INTERNAL_BUF*)(*p_buffer)); | |
1343 #endif | |
1344 | |
1345 /* increase memory use counter */ | |
1346 mb->cur_memory_used += rvf_get_buf_size( (UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF) ); | |
1347 ( (T_RVF_INTERNAL_BUF *) (*p_buffer))->header.external.mb_id = mb_id; | |
1348 ( (T_RVF_INTERNAL_BUF *) (*p_buffer))->header.external.mb_expected = RVF_INVALID_MB_ID; | |
1349 | |
1350 *p_buffer = (UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF); | |
1351 | |
1352 #if RVF_ENABLE_STATS | |
1353 if ( mb->cur_memory_used > mb->max_reached ) | |
1354 { mb->max_reached = mb->cur_memory_used; | |
1355 } | |
1356 mb->required_size += buffer_size; | |
1357 mb->num_buf++; | |
1358 #endif | |
1359 | |
1360 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_enable(); /* exit critical section */ | |
1361 | |
1362 /* return the correct flag */ | |
1363 if ( mb->cur_memory_used > mb->watermark ) | |
1364 { return RVF_YELLOW; | |
1365 } | |
1366 else | |
1367 { return RVF_GREEN; | |
1368 } | |
1369 } | |
1370 | |
1371 /******************************************************************************* | |
1372 ** | |
1373 ** Function rvf_count_buf | |
1374 ** | |
1375 ** Description Called by an application to change the memory bank on which a buffer is counted | |
1376 ** | |
1377 ** Parameters: new memory bank id, | |
1378 ** pointer to the buffer. | |
1379 ** | |
1380 ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok, | |
1381 ** RVF_YELLOW if watermark limit has been reached, | |
1382 ** RVF_RED if max size has been reached | |
1383 ** | |
1384 *******************************************************************************/ | |
1385 T_RVF_MB_STATUS rvf_count_buf(T_RVF_MB_ID mb_id, T_RVF_BUFFER * p_buffer) | |
1386 { T_RVF_INTERNAL_BUF * buf; | |
1387 UINT32 buf_size; | |
1388 T_RVF_MB * new_mb; | |
1389 T_RVF_MB * old_mb; | |
1390 | |
1391 /* checking for invalid memory bank IDs */ | |
1392 if (mb_id >= RVF_MAX_REAL_MB) | |
1393 { | |
1394 #ifdef RVM_DAR_SWE | |
1395 dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR, | |
1396 DAR_ASCII_FORMAT, | |
1397 RVM_USE_ID); | |
1398 #else | |
1399 rvf_send_trace (RVF_INVALID_MD_ID_ERRROR, | |
1400 sizeof (RVF_INVALID_MD_ID_ERRROR) - 1, | |
1401 NULL_PARAM, | |
1402 RV_TRACE_LEVEL_ERROR, | |
1403 RVM_USE_ID); | |
1404 #endif | |
1405 return RVF_RED; | |
1406 } | |
1407 buf = (T_RVF_INTERNAL_BUF *) ( (UINT8 *) p_buffer - sizeof(T_RVF_INTERNAL_BUF) ); | |
1408 new_mb = &rvf_banks[mb_id]; | |
1409 old_mb = &rvf_banks[buf->header.external.mb_id]; | |
1410 | |
1411 /* get the size of the buffer and try to count it on the new mb */ | |
1412 buf_size = rvf_get_buf_size( p_buffer ); | |
1413 | |
1414 if ( ( new_mb->cur_memory_used + buf_size ) < new_mb->max ) | |
1415 { /* there is enough memory in the new mb */ | |
1416 | |
1417 if ( buf->header.external.mb_expected != RVF_INVALID_MB_ID ) | |
1418 { /* remove the buffer from the list of waiting buffers in mb expected */ | |
1419 _remove_from_list( buf, &rvf_banks[buf->header.external.mb_expected] ); | |
1420 buf->header.external.mb_expected = RVF_INVALID_MB_ID; | |
1421 } | |
1422 | |
1423 rvf_disable(20); /* enter critical section */ | |
1424 | |
1425 /* decrease the memory used in the old mb */ | |
1426 old_mb->cur_memory_used -= buf_size; | |
1427 | |
1428 /* increase memory used in the new mb */ | |
1429 new_mb->cur_memory_used += buf_size; | |
1430 | |
1431 rvf_enable(); /* exit critical section */ | |
1432 | |
1433 /* call the callback function if state of the old mb switches to RVF_GREEN and there is no buffer waiting */ | |
1434 if ( (old_mb->cur_memory_used < old_mb->watermark) && (old_mb->first_buffer_index == RVF_INVALID_INDEX) && (old_mb->returned_red == TRUE) && ( old_mb->func != NULL) ) | |
1435 { old_mb->returned_red = FALSE; | |
1436 old_mb->func( buf->header.external.mb_id); | |
1437 } | |
1438 else | |
1439 { /* count as many waiting buffers as possible on the old mb */ | |
1440 while( (old_mb->first_buffer_index != RVF_INVALID_INDEX) && (rvf_count_buf( buf->header.external.mb_id, (UINT8 *) (waiting_buffers[old_mb->first_buffer_index]) + sizeof(T_RVF_INTERNAL_BUF)) != RVF_RED) ); | |
1441 if ( (old_mb->cur_memory_used < old_mb->watermark) && (old_mb->first_buffer_index == RVF_INVALID_INDEX) && (old_mb->returned_red == TRUE) && ( old_mb->func != NULL) ) | |
1442 { old_mb->returned_red = FALSE; | |
1443 old_mb->func( buf->header.external.mb_id); | |
1444 } | |
1445 } | |
1446 /* change mb_id of the buffer */ | |
1447 buf->header.external.mb_id = mb_id; | |
1448 | |
1449 | |
1450 | |
1451 #if RVF_ENABLE_STATS | |
1452 if ( new_mb->cur_memory_used > new_mb->max_reached ) | |
1453 { new_mb->max_reached = new_mb->cur_memory_used; | |
1454 } | |
1455 #endif | |
1456 | |
1457 if ( new_mb->cur_memory_used > new_mb->watermark ) | |
1458 { return RVF_YELLOW; | |
1459 } | |
1460 else | |
1461 { return RVF_GREEN; | |
1462 } | |
1463 } | |
1464 else | |
1465 { /* there is not enough memory in the new mb_id */ | |
1466 if ( buf->header.external.mb_expected != RVF_INVALID_MB_ID) /* remove the buffer from old expected mb */ | |
1467 { _remove_from_list( buf, &rvf_banks[ buf->header.external.mb_expected] ); | |
1468 } | |
1469 /* enqueue the buffer in the list of waiting buffer */ | |
1470 buf->header.external.mb_expected = mb_id; | |
1471 _add_to_list( buf, new_mb ); | |
1472 new_mb->returned_red = TRUE; | |
1473 return RVF_RED; | |
1474 } | |
1475 } | |
1476 | |
1477 /******************************************************************************* | |
1478 ** | |
1479 ** Function rvf_free_buf | |
1480 ** | |
1481 ** Description Called by an application to free a buffer | |
1482 ** | |
1483 ** Parameters: buffer pointer | |
1484 ** | |
1485 ** Returns T_RVF_RET: T_RVF_OK if succesful, | |
1486 ** | |
1487 *******************************************************************************/ | |
1488 T_RVF_RET rvf_free_buf( T_RVF_BUFFER * p_buffer) | |
1489 { T_RVF_INTERNAL_BUF * buf; | |
1490 T_RVF_MB * mb; | |
1491 T_RVF_MB_ID mb_id; | |
1492 UINT32 buf_size; | |
1493 | |
1494 | |
1495 buf = USER2MEM(p_buffer); | |
1496 | |
1497 mb_id = buf->header.external.mb_id; | |
1498 mb = &rvf_banks[mb_id]; | |
1499 buf_size = rvf_get_buf_size(p_buffer); | |
1500 | |
1501 /* do not need to change the mb id of the buffer, since it will be overwritten by p_prev */ | |
1502 | |
1503 /* free the buffer */ | |
1504 if ( !_release_buf(buf) ) | |
1505 { return RVF_MEMORY_ERR; | |
1506 } | |
1507 | |
1508 #if RVF_ENABLE_STATS | |
1509 mem_in_use -= buf_size + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD; | |
1510 #endif | |
1511 | |
1512 rvf_disable(20); /* enter critical section */ | |
1513 | |
1514 /* decrease mb memory use */ | |
1515 mb->cur_memory_used -= buf_size; | |
1516 | |
1517 rvf_enable(); /* exit critical section */ | |
1518 | |
1519 | |
1520 /* call the callback function if state of the mb switches to RVF_GREEN and there is no buffer waiting */ | |
1521 if ( (mb->returned_red == TRUE) && (mb->cur_memory_used < mb->watermark) && ( mb->first_buffer_index == RVF_INVALID_INDEX) && ( mb->func != NULL) ) | |
1522 { mb->returned_red = FALSE; | |
1523 mb->func( mb_id); | |
1524 } | |
1525 else | |
1526 { /* count as many waiting buffers as possible on the mb */ | |
1527 while( (mb->first_buffer_index != RVF_INVALID_INDEX) && (rvf_count_buf( mb_id, (UINT8 *) (waiting_buffers[mb->first_buffer_index]) + sizeof(T_RVF_INTERNAL_BUF)) != RVF_RED) ); | |
1528 if ( (mb->cur_memory_used < mb->watermark) && ( mb->first_buffer_index == RVF_INVALID_INDEX) && (mb->returned_red == TRUE) && ( mb->func != NULL) ) | |
1529 { mb->returned_red = FALSE; | |
1530 mb->func( mb_id); | |
1531 } | |
1532 } | |
1533 | |
1534 return RVF_OK; | |
1535 } | |
1536 | |
1537 | |
1538 /******************************************************************************* | |
1539 ** | |
1540 ** Function rvf_set_callback_func | |
1541 ** | |
1542 ** Description Called the first time an application wants to set the callback | |
1543 ** function associated to a memory bank. | |
1544 ** | |
1545 ** Parameters: memory bank id, pointer to the callback function. | |
1546 ** | |
1547 ** Returns T_RVF_RET: T_RVF_OK if succesful, | |
1548 ** | |
1549 *******************************************************************************/ | |
1550 T_RVF_RET rvf_set_callback_func(T_RVF_MB_ID mb_id, MB_CALLBACK_FUNC func) | |
1551 { T_RVF_MB * mb; | |
1552 | |
1553 /* checking for invalid memory bank IDs */ | |
1554 if (mb_id >= RVF_MAX_REAL_MB) | |
1555 return RVF_INVALID_PARAMETER; | |
1556 mb = &rvf_banks[mb_id]; | |
1557 if ( (mb->max != 0) && (mb->func == NULL) ) /* if the mb has been created and the callback func has never been set */ | |
1558 { mb->func = func; | |
1559 return RVF_OK; | |
1560 } | |
1561 return RVF_INVALID_PARAMETER; | |
1562 } | |
1563 | |
1564 | |
1565 /******************************************************************************* | |
1566 ** | |
1567 ** Function rvf_change_callback_func | |
1568 ** | |
1569 ** Description Called by an application to change the callback | |
1570 ** function associated to a memory bank. | |
1571 ** It means the callback function has to be set before. | |
1572 ** | |
1573 ** Parameters: memory bank id, pointer to the callback function. | |
1574 ** | |
1575 ** Returns T_RVF_RET: T_RVF_OK if succesful, | |
1576 ** | |
1577 *******************************************************************************/ | |
1578 T_RVF_RET rvf_change_callback_func(T_RVF_MB_ID mb_id, MB_CALLBACK_FUNC func) | |
1579 { T_RVF_MB * mb; | |
1580 | |
1581 /* checking for invalid memory bank IDs */ | |
1582 if (mb_id >= RVF_MAX_REAL_MB) | |
1583 return RVF_INVALID_PARAMETER; | |
1584 mb = &rvf_banks[mb_id]; | |
1585 if ( (mb->max != 0) && (mb->func != NULL) ) /* if the mb has been created and the callback func has already been set */ | |
1586 { mb->func = func; | |
1587 return RVF_OK; | |
1588 } | |
1589 return RVF_INVALID_PARAMETER; | |
1590 } | |
1591 | |
1592 #ifdef _WINDOWS_ | |
1593 /******************************************************************************* | |
1594 ** | |
1595 ** Function _rvf_window_dump_mem | |
1596 ** | |
1597 ** Description Called by a C++ object to update the graphical display of | |
1598 ** memory | |
1599 ** | |
1600 ** Parameters: Opaque pointer to C++ object | |
1601 ** | |
1602 ** Returns void | |
1603 ** | |
1604 ** WARNING DON'T CHANGE THE SYNTAX OF DISPLAYED DATAS SINCE | |
1605 ** THEY ARE PARSED TO DISPLAY GRAPHICALLY THE MEMORY | |
1606 ** STATUS | |
1607 ** | |
1608 *******************************************************************************/ | |
1609 void _rvf_window_dump_mem(void *m) | |
1610 { | |
1611 | |
1612 | |
1613 #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */ | |
1614 char mb_info[100]; | |
1615 UINT16 num_mb, num_buf, index; | |
1616 UINT32 total_mem_size = 0; | |
1617 UINT32 total_max_used = 0; | |
1618 UINT32 total_cur_used = 0; | |
1619 T_RVF_MB * mb; | |
1620 | |
1621 | |
1622 for ( num_mb = 0; num_mb < RVF_MAX_TOTAL_MB; num_mb++ ) | |
1623 { | |
1624 /* trace the mb if it has been created*/ | |
1625 if ( rvf_name_id[num_mb].mb_params.size > 0 ) | |
1626 { mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1627 num_buf = 0; | |
1628 index = mb->first_buffer_index; | |
1629 while ( index != RVF_INVALID_INDEX) | |
1630 { num_buf++; | |
1631 index = next_buffer[index]; | |
1632 } | |
1633 strcpy(mb_info,rvf_name_id[num_mb].mb_name); | |
1634 mb_info[10]='\0'; | |
1635 AddNewState(m,mb_info, | |
1636 mb->cur_memory_used,mb->max_reached,mb->watermark,mb->max); | |
1637 | |
1638 | |
1639 total_mem_size += mb->max; | |
1640 total_max_used += mb->max_reached; | |
1641 total_cur_used += mb->cur_memory_used; | |
1642 } | |
1643 } | |
1644 | |
1645 #endif /* RVF_ENABLE_STATS */ | |
1646 } | |
1647 | |
1648 #endif | |
1649 | |
1650 /******************************************************************************* | |
1651 ** | |
1652 ** Function rvf_dump_mem | |
1653 ** | |
1654 ** Description Called by an application to dump mb state and display statistics | |
1655 ** | |
1656 ** Parameters: None | |
1657 ** | |
1658 ** Returns void | |
1659 ** | |
1660 ** WARNING DON'T CHANGE THE SYNTAX OF DISPLAYED DATAS SINCE | |
1661 ** THEY ARE PARSED TO DISPLAY GRAPHICALLY THE MEMORY | |
1662 ** STATUS | |
1663 ** | |
1664 *******************************************************************************/ | |
1665 void rvf_dump_mem() | |
1666 { | |
1667 #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */ | |
1668 char mb_info[100]; | |
1669 UINT16 num_mb, num_buf, index; | |
1670 UINT32 total_mem_size = 0; | |
1671 UINT32 total_max_used = 0; | |
1672 UINT32 total_cur_used = 0; | |
1673 T_RVF_MB * mb; | |
1674 | |
1675 | |
1676 /* display memory required, obtained and ratio */ | |
1677 rvf_send_trace("MEM STAT: Total memory required", 31, required_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1678 rvf_send_trace("MEM STAT: Total memory obtained", 31, obtained_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1679 rvf_send_trace("MEM STAT: Total memory used ", 31, used_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1680 sprintf( mb_info,"MEM STAT: Mem usage ratio : %010f%%", ( (double)(required_size) / (double)(obtained_size) ) *100 ); | |
1681 rvf_send_trace(mb_info, 44, NULL_PARAM , RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1682 | |
1683 rvf_send_trace("*** START DUMPING MEMORY BANK ***", 33, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1684 /* for each mb, display its name, its id, its cur_size, its watermark, its limit, its max reached, the number of callback functions enqueued, | |
1685 (the requested size, the number of allocated buffer), the average buffer size for this mb */ | |
1686 rvf_send_trace("**MB_NAME* Id Used_mem Watermark Limit Peak Nb_buff Avg_buf_size", 67, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1687 | |
1688 for ( num_mb = 0; num_mb < RVF_MAX_TOTAL_MB; num_mb++ ) | |
1689 { | |
1690 /* trace the mb if it has been created*/ | |
1691 if ( rvf_name_id[num_mb].mb_params.size > 0 ) | |
1692 { mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1693 num_buf = 0; | |
1694 index = mb->first_buffer_index; | |
1695 while ( index != RVF_INVALID_INDEX) | |
1696 { num_buf++; | |
1697 index = next_buffer[index]; | |
1698 } | |
1699 sprintf( mb_info, "%10.10s %2d %6d %6d %6d %6d %2d %6d", | |
1700 rvf_name_id[num_mb].mb_name, rvf_name_id[num_mb].mb_id, | |
1701 mb->cur_memory_used, mb->watermark, mb->max, mb->max_reached, num_buf, | |
1702 mb->num_buf == 0? 0:mb->required_size / mb->num_buf); | |
1703 | |
1704 rvf_send_trace( mb_info, 67, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1705 | |
1706 total_mem_size += mb->max; | |
1707 total_max_used += mb->max_reached; | |
1708 total_cur_used += mb->cur_memory_used; | |
1709 } | |
1710 } | |
1711 sprintf( mb_info, "TOTAL: ******** %6d********** %6d %6d", | |
1712 total_cur_used, total_mem_size, total_max_used ); | |
1713 | |
1714 rvf_send_trace( mb_info, 46, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1715 | |
1716 #endif /* RVF_ENABLE_STATS */ | |
1717 } | |
1718 | |
1719 | |
1720 /******************************************************************************* | |
1721 ** | |
1722 ** Function rvf_get_available_mem | |
1723 ** | |
1724 ** Description Called to get the total size of the memory and the used size. | |
1725 ** | |
1726 ** Parameters: (return) UINT32 * total_size: contains the number of bytes in the memory. | |
1727 ** (return) UINT32 * used_size: contains the number of used bytes in the memory. | |
1728 ** | |
1729 ** Returns T_RVF_RET: RVF_OK if successful, else a negative value. | |
1730 ** | |
1731 *******************************************************************************/ | |
1732 T_RVF_RET rvf_get_available_mem( UINT32 * total_size, UINT32 * used_size ) | |
1733 { | |
1734 UINT16 count; | |
1735 *total_size = 0; | |
1736 *used_size = 0; | |
1737 | |
1738 /* check if there is enough available physical memory (static or dynamic): if Sum(mb size) <= Sum(pool size)*/ | |
1739 for ( count = 0; count < _rvf_get_number_of_pool(); count ++ ) /* sum the memory in pools */ | |
1740 { *total_size += _rvf_pools[count].pool_size; | |
1741 } | |
1742 /* sum the memory required by existing mb */ | |
1743 for ( count = 0; count < RVF_MAX_REAL_MB; count ++ ) | |
1744 { *used_size += rvf_banks[count].max; | |
1745 } | |
1746 | |
1747 return RVF_OK; | |
1748 } | |
1749 | |
1750 | |
1751 /******************************************************************************* | |
1752 ** | |
1753 ** Function rvf_get_mb_param | |
1754 ** | |
1755 ** Description return the parameters of a specific memory bank | |
1756 ** | |
1757 ** Parameters: T_RVF_MB_NAME: name of the memory bank | |
1758 ** (return) T_RVF_MB_PARAM*: parameter of the memory bank. | |
1759 ** | |
1760 ** Returns T_RVF_RET: RVF_OK if successful, else a negative value. | |
1761 ** | |
1762 *******************************************************************************/ | |
1763 T_RVF_RET rvf_get_mb_param( T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM * param) | |
1764 { UINT8 num_mb; | |
1765 | |
1766 /* find the mb name in the array */ | |
1767 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1768 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1769 { return RVF_INVALID_PARAMETER; | |
1770 } | |
1771 | |
1772 /* copy the parameters of the memory bank */ | |
1773 *param = rvf_name_id[num_mb].mb_params; | |
1774 | |
1775 return RVF_OK; | |
1776 } | |
1777 | |
1778 | |
1779 /******************************************************************************* | |
1780 ** | |
1781 ** Function rvf_set_mb_param | |
1782 ** | |
1783 ** Description change the parameters of a specific memory bank | |
1784 ** | |
1785 ** Parameters: T_RVF_MB_NAME: name of the memory bank | |
1786 ** T_RVF_MB_PARAM*: parameter of the memory bank. | |
1787 ** | |
1788 ** Returns T_RVF_RET: RVF_OK if successful, else a negative value. | |
1789 ** | |
1790 *******************************************************************************/ | |
1791 T_RVF_RET rvf_set_mb_param( T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM * param) | |
1792 { UINT8 num_mb; | |
1793 T_RVF_MB_ID mb_id; | |
1794 T_RVF_MB * mb; | |
1795 | |
1796 /* find the mb name in the array */ | |
1797 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1798 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1799 { return RVF_INVALID_PARAMETER; | |
1800 } | |
1801 | |
1802 mb_id = rvf_name_id[num_mb].mb_id; | |
1803 mb = &rvf_banks[ mb_id ]; | |
1804 | |
1805 rvf_disable(20); /* enter critical section */ | |
1806 | |
1807 /* decrease the mb param by the old parameters */ | |
1808 mb->watermark -= rvf_name_id[num_mb].mb_params.watermark; | |
1809 mb->max -= rvf_name_id[num_mb].mb_params.size; | |
1810 | |
1811 /* save the mb parameters */ | |
1812 rvf_name_id[num_mb].mb_params.size = param->size; | |
1813 rvf_name_id[num_mb].mb_params.watermark = param->watermark; | |
1814 | |
1815 /* increase the mb param by the new parameters */ | |
1816 mb->watermark += param->watermark; | |
1817 mb->max += param->size; | |
1818 | |
1819 rvf_enable(); /* exit critical section */ | |
1820 | |
1821 /* dequeue callback functions if state switches to RVF_GREEN */ | |
1822 | |
1823 return RVF_OK; | |
1824 } | |
1825 | |
1826 | |
1827 | |
1828 | |
1829 /******************************************************************************* | |
1830 ** | |
1831 ** Function rvf_empty_mailboxes | |
1832 ** | |
1833 ** Description Called by rvf_exit_task to empty a task's mailboxes before | |
1834 ** killing it | |
1835 ** | |
1836 ** Parameters: task_id: task of wich the mailboxes have to be emptied | |
1837 ** | |
1838 ** Returns RV_OK | |
1839 ** | |
1840 *******************************************************************************/ | |
1841 T_RV_RET _rvf_empty_mailboxes (T_RVF_G_ADDR_ID task_id) | |
1842 { | |
1843 void * p_buf = NULL; | |
1844 T_RVF_INTERNAL_BUF * p_hdr; | |
1845 UINT8 mbox_id = 0; | |
1846 | |
1847 if (task_id >= MAX_RVF_TASKS) | |
1848 { | |
1849 rvf_send_trace( "RVF: rvf_empty_mbox(): invalid taskid: ", 39, task_id, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
1850 return RVF_INVALID_PARAMETER; | |
1851 } | |
1852 | |
1853 for (mbox_id = 0; mbox_id< RVF_NUM_TASK_MBOX; mbox_id++) | |
1854 { /* while the chained list is not empty */ | |
1855 /*while ( OSTaskQFirst[task_id][mbox_id] ) | |
1856 { | |
1857 rvf_disable(9); | |
1858 | |
1859 p_hdr = OSTaskQFirst[task_id][mbox_id]; | |
1860 OSTaskQFirst[task_id][mbox_id] = p_hdr->p_next; | |
1861 */ | |
1862 while ( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id] ) | |
1863 { | |
1864 rvf_disable(9); | |
1865 | |
1866 p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id]; | |
1867 pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id] = p_hdr->p_next; | |
1868 | |
1869 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
1870 /* set as unlinked */ | |
1871 RVF_SET_BUF_UNLINKED(p_hdr); | |
1872 #endif | |
1873 | |
1874 p_buf = (UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF); | |
1875 | |
1876 rvf_enable(); /* exit critical section */ | |
1877 | |
1878 rvf_free_buf(p_buf); | |
1879 } | |
1880 } | |
1881 | |
1882 | |
1883 return (RV_OK); | |
1884 } | |
1885 | |
1886 | |
1887 /******************************************************************************* | |
1888 ** | |
1889 ** Function rvf_scan_next | |
1890 ** | |
1891 ** Description return the next item in the queue if any. | |
1892 ** If the end of the queue is reached, returns NULL. | |
1893 ** If current item is NULL, returns the first item in the queue. | |
1894 ** | |
1895 ** Returns NULL if the end of the queue is reached, else a pointer to the buffer. | |
1896 ** | |
1897 *******************************************************************************/ | |
1898 T_RVF_BUFFER * rvf_scan_next (T_RVF_BUFFER_Q * p_q, T_RVF_BUFFER * p_buf) | |
1899 { | |
1900 T_RVF_INTERNAL_BUF *p_hdr; | |
1901 | |
1902 if (!p_q->count) /* if the queue is empty */ | |
1903 return (NULL); | |
1904 | |
1905 if (p_buf == NULL) /* if current item == NULL, returns the first one */ | |
1906 { | |
1907 return (T_RVF_BUFFER*)p_q->p_first; | |
1908 } | |
1909 | |
1910 rvf_disable(12); /* enter critical section */ | |
1911 | |
1912 p_hdr = (T_RVF_INTERNAL_BUF *)((UINT8 *)p_buf - sizeof(T_RVF_INTERNAL_BUF)); | |
1913 p_hdr = p_hdr->p_next; | |
1914 if (p_hdr != NULL) | |
1915 { p_hdr = (T_RVF_INTERNAL_BUF*) ((UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF)); | |
1916 } | |
1917 | |
1918 rvf_enable(); | |
1919 | |
1920 return (T_RVF_BUFFER*)p_hdr; | |
1921 } | |
1922 | |
1923 | |
1924 /******************************************************************************* | |
1925 ** | |
1926 ** Function rvf_remove_from_queue | |
1927 ** | |
1928 ** Description remove a specific item from a queue | |
1929 ** | |
1930 ** Returns RVF_OK if the item is removed, RVF_INTERNAL_ERR else. | |
1931 ** | |
1932 *******************************************************************************/ | |
1933 T_RVF_RET rvf_remove_from_queue (T_RVF_BUFFER_Q * p_q, T_RVF_BUFFER * p_buf) | |
1934 { | |
1935 T_RVF_INTERNAL_BUF *p_hdr; | |
1936 T_RVF_INTERNAL_BUF *p_target; | |
1937 | |
1938 | |
1939 if (!p_q->count) /* if the queue is empty */ | |
1940 return (RVF_INTERNAL_ERR); | |
1941 | |
1942 rvf_disable(12); /* enter critical section */ | |
1943 | |
1944 /* find the specific item in the queue */ | |
1945 p_target = USER2MEM((UINT8*)p_buf); | |
1946 p_hdr = USER2MEM( (UINT8 *)p_q->p_first); | |
1947 | |
1948 if( p_hdr == p_target ) | |
1949 { /* the specific item is the first one */ | |
1950 rvf_dequeue( p_q); | |
1951 rvf_enable(); | |
1952 return (RVF_OK); | |
1953 } | |
1954 | |
1955 while( (p_hdr->p_next != p_target) && (p_hdr->p_next != NULL) ) | |
1956 { p_hdr = p_hdr->p_next; | |
1957 } | |
1958 | |
1959 if( p_hdr->p_next == NULL) /* item not found */ | |
1960 { rvf_enable(); | |
1961 return (RVF_INTERNAL_ERR); | |
1962 } | |
1963 | |
1964 | |
1965 p_hdr->p_next = p_target->p_next; | |
1966 p_q->count--; | |
1967 | |
1968 /* if we removed the last buffer */ | |
1969 if (p_q->p_last == p_buf) | |
1970 { p_q->p_last = p_hdr + sizeof(T_RVF_INTERNAL_BUF); | |
1971 } | |
1972 | |
1973 p_target->p_next = NULL; | |
1974 | |
1975 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
1976 /* set as unlinked */ | |
1977 RVF_SET_BUF_UNLINKED(p_target); | |
1978 #endif | |
1979 | |
1980 rvf_enable(); /* exit critical section */ | |
1981 | |
1982 return (RVF_OK); | |
1983 } | |
1984 | |
1985 /******************************************************************************* | |
1986 ** | |
1987 ** Function rvf_dump_pool | |
1988 ** | |
1989 ** Description Called by an application to dump memory pool usage | |
1990 ** | |
1991 ** Parameters: None | |
1992 ** | |
1993 ** Returns void | |
1994 ** | |
1995 *******************************************************************************/ | |
1996 void rvf_dump_pool() | |
1997 { | |
1998 #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */ | |
1999 | |
2000 UINT16 num_pool; | |
2001 UINT32 total_mem = 0; | |
2002 | |
2003 /* display memory stats */ | |
2004 rvf_send_trace("*** START DUMPING MEMORY ***", 28, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
2005 | |
2006 /* display the total amount of memory available in the system */ | |
2007 /* and the total amount of memory currently in use */ | |
2008 for( num_pool = 0; num_pool < _rvf_get_number_of_pool(); num_pool++) | |
2009 { total_mem += _rvf_pools[num_pool].pool_size; | |
2010 } | |
2011 | |
2012 rvf_send_trace( "Total memory available ", 23, total_mem, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
2013 rvf_send_trace( "Memory currently in use", 23, mem_in_use, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
2014 | |
2015 #endif /* RVF_ENABLE_STATS */ | |
2016 } | |
2017 | |
2018 static void rvf_free_protected_buf(void *buf) | |
2019 { | |
2020 rvf_free_buf(buf); | |
2021 } | |
2022 | |
2023 void rvf_get_protected_buf(T_RVF_MB_ID mb_id, UINT32 buffer_size, T_RVF_BUFFER** p_buffer) | |
2024 { | |
2025 T_RVF_MB_STATUS err; | |
2026 err=rvf_get_buf(mb_id,buffer_size,p_buffer); | |
2027 if (err==RVF_GREEN) | |
2028 { | |
2029 struct _protectedPtr_ *ptr; | |
2030 struct _exceptionContext_ *context; | |
2031 | |
2032 context=_currentExceptionContext_[rvf_get_taskid()]; | |
2033 err=rvf_get_buf(mb_id,sizeof(struct _protectedPtr_),(void*)&ptr); | |
2034 ptr->next=NULL; | |
2035 ptr->previous=NULL; | |
2036 ptr->ptr=*p_buffer; | |
2037 ptr->func=rvf_free_protected_buf; | |
2038 | |
2039 if (err==RVF_GREEN) | |
2040 { | |
2041 if (context->stack==NULL) | |
2042 { | |
2043 context->stack=ptr; | |
2044 } | |
2045 else | |
2046 { | |
2047 ptr->previous=context->stack; | |
2048 context->stack->next=ptr; | |
2049 context->stack=ptr; | |
2050 } | |
2051 } | |
2052 else | |
2053 { | |
2054 rvf_free_buf(*p_buffer); | |
2055 } | |
2056 } | |
2057 if (err!=RVF_GREEN) | |
2058 throw(E_not_enough_memory); | |
2059 } | |
2060 | |
2061 //TISHMMS Project | |
2062 /* add by xmzhou_trace_string to trace debug trace message */ | |
2063 void xmzhou_trace_string(char * string2trace) | |
2064 { | |
2065 rvf_send_trace(string2trace,strlen(string2trace),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2066 } | |
2067 | |
2068 void xmzhou_trace_string_value(char * string2trace,UINT32 value) | |
2069 { | |
2070 rvf_send_trace(string2trace,strlen(string2trace),value, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2071 } | |
2072 | |
2073 static void mychar2hex(char ch, char *str) | |
2074 { | |
2075 unsigned char h_nibble = (ch >> 4) & 0x0F; | |
2076 unsigned char l_nibble = ch & 0x0F; | |
2077 | |
2078 if (h_nibble < 10) | |
2079 str[0] = 48 + h_nibble; | |
2080 else | |
2081 str[0] = 55 + h_nibble; | |
2082 | |
2083 if (l_nibble < 10) | |
2084 str[1] = 48 + l_nibble; | |
2085 else | |
2086 str[1] = 55 + l_nibble; | |
2087 } | |
2088 | |
2089 void xmzhou_trace_n_bytes(char * buffer0, UINT32 len) | |
2090 { | |
2091 int i; | |
2092 int traced_len=0; | |
2093 char mybuffer[40]; | |
2094 char *tracebuffer; | |
2095 | |
2096 if(buffer0==NULL) return; | |
2097 | |
2098 xmzhou_trace_string_value("xmzhou dumping data length=",len); | |
2099 xmzhou_trace_string("-------"); | |
2100 | |
2101 | |
2102 while(traced_len<len){ | |
2103 | |
2104 if((len-traced_len)>=16){ | |
2105 tracebuffer=mybuffer; | |
2106 for (i = 0; i < 16; i++) { | |
2107 mychar2hex (buffer0[traced_len+i], tracebuffer); | |
2108 tracebuffer += 2; | |
2109 } | |
2110 traced_len+=16; | |
2111 *tracebuffer = '\0'; | |
2112 rvf_send_trace(mybuffer,strlen(mybuffer),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2113 rvf_delay(20); | |
2114 }else{ | |
2115 tracebuffer=mybuffer; | |
2116 for(i=0;i<(len-traced_len);i++) | |
2117 { | |
2118 mychar2hex (buffer0[traced_len+i], tracebuffer); | |
2119 tracebuffer += 2; | |
2120 } | |
2121 *tracebuffer = '\0'; | |
2122 rvf_send_trace(mybuffer,strlen(mybuffer),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2123 rvf_delay(20); | |
2124 break; | |
2125 } | |
2126 | |
2127 } | |
2128 } |