diff gsm-fw/services/ffs/task.c @ 212:3ebe6409e8bc

gsm-fw/services/ffs: task.c integrated
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 06 Jan 2014 04:15:30 +0000
parents
children fee45482aa2a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/services/ffs/task.c	Mon Jan 06 04:15:30 2014 +0000
@@ -0,0 +1,434 @@
+/******************************************************************************
+ * Flash File System (ffs)
+ * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
+ *
+ * FFS task. ONLY for target!
+ *
+ * $Id: task.c 1.48.1.1.1.24 Thu, 18 Dec 2003 10:50:52 +0100 tsj $
+ *
+ ******************************************************************************/
+
+#include "../../include/config.h"
+#include "ffs.h"
+#include "core.h"
+#include "task.h"
+#include "ffstrace.h" 
+#include "../../riviera/rvm/rvm_use_id_list.h"
+
+/******************************************************************************
+ * Globals and function prototypes
+ ******************************************************************************/
+
+extern UINT8 pcm_init(void);
+void ffs_task(void);
+
+static effs_t ffs_init_status;
+req_id_t request_id_last = 0;
+
+T_OS_MB_ID ffs_mb_id;
+UINT16     ffs_addr_id;
+
+/******************************************************************************
+ * FFS Test Task
+ ******************************************************************************/
+
+// For this to work, change:
+// 1. MAX_RVF_TASKS define in rvf_target.h
+
+// Note that the FFS_TEST_TASK_ID is set one too low! We assume we are lucky
+// that no other task has the same ID...
+
+#if (WITH_TFFS == 1)
+
+#define FFS_TEST_STACK_SIZE 1024
+
+#define FFS_TEST_TASK_ID    (MAX_RVF_TASKS - 1 - 1)
+
+void ffs_test_task(void);
+void test_init(int keepgoing);
+int  test_run(char *testname);
+
+static uint8 ffs_test_stack[FFS_TEST_STACK_SIZE];
+
+// This is the string of test cases to run by calling test_run(). This
+// string as written to from tmffs module.
+char ffs_test_string[128];
+
+// Delay for <delay> milliseconds
+void tffs_delay(int delay)
+{
+    delay = 14 * delay / 64; // approx. same as division by 60/13
+    OS_DELAY(delay);
+}
+
+UINT32 rvf_get_tick_count(void);
+// Timer functions for benchmarking
+UINT32 tffs_timer_begin(void)
+{
+    return rvf_get_tick_count(); 
+}
+
+UINT32 tffs_timer_end(UINT32 time_begin)
+{
+    // return current time minus time_begin
+    UINT32 ticks;
+
+    ticks = rvf_get_tick_count();
+
+    return (ticks - time_begin) * 60 / 13;
+}
+
+void ffs_test_task(void)
+{
+    effs_t error;
+
+    OS_DELAY(217); // wait approx. 1000ms
+
+    ttw(str(TTrTest, "ffs_test_task()" NL));
+
+    while (1) {
+        OS_DELAY(217); // wait approx. 1000ms
+
+        // Poll to see if we have tests to run... We know that the writer of
+        // ffs_test_string has a higher priority than us, so it is properly
+        // written when we reach here.
+        if (*ffs_test_string) {
+            test_init(0);
+            error = test_run(ffs_test_string);
+            *ffs_test_string = 0;
+
+            if (error == 0)
+                ttw(str(TTrTest, "TEST succeeded" NL));
+            else
+                ttw(ttr(TTrTest, "TEST cases failed: %d" NL, error));
+        }
+    }
+}
+
+#endif // End of WITH_TFFS
+
+/******************************************************************************
+ * Target Platform Abstraction Functions
+ ******************************************************************************/
+
+req_id_t request_id_get(void)
+{
+    extern uint32 int_disable(void);
+    extern void int_enable(uint32 tmp);
+    uint32 cprs;
+
+    // We disable interrupt to avoid any other tasks to get the same id.
+    cprs = int_disable();
+    request_id_last++;
+
+    if (request_id_last < 0)
+        request_id_last = 0;
+
+    int_enable(cprs);
+
+    return request_id_last;
+}
+
+void *target_malloc(unsigned int size)
+{
+    char *buf;
+
+#if (_RVF == 1)
+    if ((rvf_get_buf(ffs_mb_id, size, (T_RVF_BUFFER*) &buf)) == RVF_RED)
+        return 0;
+    else
+        return buf;
+#else
+    return 0;
+#endif
+}
+
+void target_free(void *buf)
+{
+    int error;
+
+#if (_RVF == 1)
+    if ((error = OS_FREE(buf)) != OS_OK)
+        ttw(ttr(TTrFatal, "target_free() %d (FAILED)" NL, error));
+#endif
+}
+
+
+/******************************************************************************
+ * FFS Blocking Call Handling
+ ******************************************************************************/
+
+effs_t ffs_b_begin(struct ffs_blocking_s *fb, T_RVF_MUTEX *mutex, int *result)
+{
+    effs_t error;
+
+    if ((error = rvf_initialize_mutex(mutex)) < 0)
+    return error;
+
+    if ((error = rvf_lock_mutex(mutex)) < 0)   // This will succeed
+    return error;
+
+    fb->result = result;
+    fb->mutex = mutex;
+
+    return EFFS_OK;
+}
+
+effs_t ffs_b_end(T_RVF_MUTEX *mutex, int result)
+{
+    effs_t error;
+
+    // Do not lock the mutex if the message send operation failed
+    if (result >= 0) 
+        // This will block the task until the mutex has been released
+        if ((error = rvf_lock_mutex(mutex)) < 0)
+            return error;
+
+    if ((error = rvf_unlock_mutex(mutex)) < 0)
+        return error;
+
+    if ((error = rvf_delete_mutex(mutex)) < 0)
+        return error;
+
+    return EFFS_OK;
+}
+
+/******************************************************************************
+ * FFS Task
+ ******************************************************************************/
+/* The below access to the intenal Nucleus variable "TCD_Interrupt_Level" is
+ * a workaround for a known Nucleus BUG (see CQ SWI-FIX-17560) */ 
+
+void ffs_main_init() 
+{
+    extern int TCD_Interrupt_Level;
+    int tmp_int_level;
+    ttr_init(TTrTask|TTrTest|TTrTestInfo);
+    //ttr_init(TTrTask|TTrTest|TTrTestInfo|TTrDrvErase|TTrDrvWrite|TTrTaskLow|TTrApi);
+    
+    tmp_int_level = TCD_Interrupt_Level;  // Backup Int level
+    TCD_Interrupt_Level = 0xC0;           // The Interrups are not yet enabled...
+    ffs_init_status = ffs_initialize();
+    TCD_Interrupt_Level = tmp_int_level;  // Restore Int level
+  
+#if 0
+    pcm_init(); // We have to call pcm_init() before G23 starts.
+#endif
+}
+
+void ffs_task_init(T_OS_MB_ID mbid, T_RVF_ADDR_ID  addr_id) 
+{
+    int error;
+
+    ffs_mb_id   = mbid;
+    ffs_addr_id = addr_id;
+
+#if (WITH_TFFS == 1)
+    error =
+        OS_CREATE_TASK((TASKPTR) ffs_test_task, FFS_TEST_TASK_ID, "TFFS",
+                       ffs_test_stack, FFS_TEST_STACK_SIZE,
+                       249,                 // priority
+		       4,                   // ET4_TASK type
+                       0,                   // no time slicing
+                       RUNNING);            // start state
+
+    ttw(ttr(TTrTask, "os_create_task('TFFS') %d" NL, error));
+#endif
+}
+
+void ffs_task()
+{
+    extern int etm_ffs_init(void);
+    struct ffs_req_s *request;
+    T_FFS_FILE_CNF *confirm_file;
+    T_FFS_STREAM_CNF *confirm_stream;
+    T_RVF_MUTEX *mutex_p;
+    int error, free_mail, os_error = OS_OK;
+    uint16 revision, manufacturer_id, device_id;
+    uint32 base;
+    fd_t fdi;
+    char *temp_path;
+    req_id_t temp_id;
+
+#if (BOARD == 34)
+    // Non formatted FFS should be formatted
+    // So we don't have to use PCTM to format it
+    if (fs.initerror == EFFS_NOFORMAT)
+    {
+        ffs_format_nb("/", 0x2BAD, 0);
+    }
+
+    ffs_InitRFCap();
+#endif
+
+    ttr(TTrTask, "ffs_init() %d" NL, ffs_init_status);
+
+    ffs_query(Q_FFS_REVISION, &revision);
+    ttr(TTrTask,"FFS revision: 0x%x" NL, revision);
+
+    ffs_query(Q_DEV_MANUFACTURER, &manufacturer_id);
+    ffs_query(Q_DEV_DEVICE,       &device_id);
+    ffs_query(Q_DEV_DRIVER,       &revision);
+    ttr(TTrTask,"FFS device, driver: 0x%02x, 0x%04x, %d" NL,
+        manufacturer_id, device_id, revision);
+
+    ffs_query(Q_DEV_BASE,   &base);
+    ffs_query(Q_DEV_BLOCKS, &revision);
+    ttr(TTrTask,"FFS base, blocks: 0x%x, %d" NL, base, revision);
+
+    ffs_query(Q_FFS_FORMAT_READ,  &manufacturer_id);
+    ffs_query(Q_FFS_FORMAT_WRITE, &device_id);
+    ttr(TTrTask,"FFS format read, write: 0x%x, 0x%x" NL NL,
+        manufacturer_id, device_id);
+
+    // If some blocks has been marked for reclaim, reclaim them now...
+    blocks_reclaim();
+
+    // We can only mkdir("pcm") *after* our mailbox has been allocated
+    // otherwise mkdir("pcm") will fail.
+    error = ffs_mkdir_nb("/pcm", 0);
+
+#if 0
+    // Register FFS to ETM database
+    error = etm_ffs_init();
+#endif
+
+    while (1)
+    {
+        OS_MAIL_WAIT(OS_MAIL_EVENT_MASK);
+        request = (struct ffs_req_s *) OS_MAIL_READ();
+
+        ttw(ttr(TTrTaskLow, "ffs_task(%d):" NL, request->cmd));
+        switch (request->cmd) {
+        case WRITE: case SEEK: case CLOSE: case FTRUNC: case FDATASYNC:
+            ttw(ttr(TTrTaskLow, "  fdi  = %d" NL, request->fdi));
+            // Save a local copy of fdi because the task we call later can
+            // modify it and we have to use the fdi if a callback is used
+            fdi = (fd_t)request->fdi; 
+            break;
+        default:
+            ttw(ttr(TTrTaskLow, "  name = %s" NL, request->path));
+            break;
+        }
+        ttw(ttr(TTrTaskLow, "  src  = 0x%x" NL, request->src));
+        ttw(ttr(TTrTaskLow, "  size = %d" NL, request->size));
+
+        if (tr_query(TTrTaskDelays))
+            OS_DELAY(5);
+
+        switch (request->cmd) {
+        case NOP:        error = EFFS_OK;                  break;
+        case FILE_WRITE: error = task_file_write(request); break;
+        case SYMLINK:    error = task_symlink(request);    break;
+        case MKDIR:      error = task_mkdir(request);      break;
+        case REMOVE:     error = task_remove(request);     break;
+        case RENAME:     error = task_rename(request);     break;
+        case FCONTROL:   error = task_fcontrol(request);   break;
+        case PREFORMAT:  error = task_preformat(request);  break;
+        case FORMAT:     error = task_format(request);     break;
+        case OPEN:       error = task_open(request);       break;
+        case WRITE:      error = task_write(request);      break;
+        case SEEK:       error = task_seek(request);       break;
+        case CLOSE:      error = task_close(request);      break;
+        case TRUNC:      error = task_trunc(request);      break;
+        case FTRUNC:     error = task_ftrunc(request);     break;
+        case FDATASYNC:  error = task_fdatasync(request);  break;
+        default:
+            ttr(TTrFatal, "FFS FATAL: bad request: %d" NL, request->cmd);
+            break;
+        }
+
+        ttw(ttr(TTrTaskLow, "ffs_task(%d) %d" NL, request->cmd, error));
+        if (tr_query(TTrTaskDelays))
+            OS_DELAY(5);
+
+        // Call-back to caller
+        mutex_p = 0;
+        if (request->cp) { 
+            free_mail = 0;  // don't free mail we will reuse it
+            // We reuse the mail we received for our call-back. Due to
+            // this reuse, we must be careful with the order of
+            // assignments. If this is a stream modify function use
+            // ffs_stream_cnf else use ffs_file_cnf  
+            
+            temp_id = request->request_id;  // Save id before we reuse the mail mem.
+            switch (request->cmd) {
+            case WRITE: case SEEK: case CLOSE: case FTRUNC: case FDATASYNC:
+                confirm_stream = (T_FFS_STREAM_CNF *) request;
+                confirm_stream->error = error;
+                confirm_stream->request_id = temp_id; 
+                confirm_stream->fdi = fdi; 
+                confirm_stream->header.msg_id = FFS_MESSAGE_OFFSET;
+            
+                if (request->cp->callback_func) {
+                    request->cp->callback_func((T_FFS_STREAM_CNF *) 
+                                               confirm_stream);
+                }
+                else if (request->cp->addr_id) {
+                    os_error = OS_MAIL_SEND(request->cp->addr_id, 
+                                            confirm_stream);
+                }
+                else {
+                    ttr(TTrFatal, "FFS WARNING: empty return path" NL);
+                    free_mail = 1;  // free mail
+                }
+                break;
+            default:
+                temp_path = (char *) request->path;
+                confirm_file = (T_FFS_FILE_CNF *) request;
+                confirm_file->error = error;
+                confirm_file->request_id = temp_id;
+                confirm_file->path = temp_path;
+                confirm_file->header.msg_id = FFS_MESSAGE_OFFSET;
+
+                if (request->cp->callback_func) {
+                    request->cp->callback_func((T_FFS_FILE_CNF *) confirm_file);
+                }   
+
+                else if (request->cp->addr_id) {
+                    os_error = OS_MAIL_SEND(request->cp->addr_id, 
+                                            confirm_file);
+                }
+                else {
+                    ttr(TTrFatal, "FFS WARNING: empty return path" NL);
+                    free_mail = 1;  // free mail
+                }
+                break;
+            }
+            
+            if (os_error != OS_OK)
+                ttr(TTrFatal, "FFS FATAL: os_send_msg() %d" NL, os_error);
+        }
+            
+        // Blocking handling / unlocking mutex
+        else if (request->fb) {   
+            // Save the pointer to the mutex and the error value (allocated
+            // on the stack by the macro FFS_BLOCKING_BEGIN)
+            mutex_p = request->fb->mutex;
+            *request->fb->result = error;  
+            free_mail = 1;  // free mail
+        }
+
+        else {
+            // The task must have been a non blocking without any callback
+            free_mail = 1; // free mail
+        }
+
+        // Free the mail memory. Note that we always free it, except when we
+        // have successfully reused it for sending a mail call-back.
+        if (free_mail == 1) {
+            os_error = OS_FREE(request);
+            if (os_error != OS_OK)
+                ttr(TTrFatal, "FFS FATAL: os_free() %d" NL, os_error);
+        }
+
+        // Blocking handling / unlocking mutex
+        if (mutex_p) {   
+            // Wake up the caller task
+            if ((os_error = rvf_unlock_mutex(mutex_p)) < 0)
+                ttr(TTrFatal, "FFS FATAL: rvf_unlock_mutex() %d" NL, os_error);
+        }
+        
+        tr_bstat();
+    }
+}