POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/middleware/portutils.c
Go to the documentation of this file.
00001 /*
00002  *                               POK header
00003  * 
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team 
00013  *
00014  * Created by julien on Thu Jan 15 23:34:13 2009 
00015  */
00016 
00024 #if defined (POK_NEEDS_PORTS_SAMPLING) || defined (POK_NEEDS_PORTS_QUEUEING)
00025 #include <types.h>
00026 #include <libc.h>
00027 #include <core/time.h>
00028 #include <middleware/port.h>
00029 #include <middleware/queue.h>
00030 
00031 extern pok_port_t    pok_ports[POK_CONFIG_NB_PORTS];
00032 extern pok_queue_t   pok_queue;
00033 extern uint8_t       pok_current_partition;
00034 
00035 pok_port_size_t pok_port_available_size (uint8_t pid)
00036 {
00037    if (pok_ports[pid].full == TRUE)
00038    {
00039       return 0;
00040    }
00041 
00042    if (pok_ports[pid].off_b < pok_ports[pid].off_e)
00043    {
00044       return (pok_ports[pid].off_b - pok_ports[pid].off_e);
00045    }
00046    else
00047    {
00048       return (pok_ports[pid].size - pok_ports[pid].off_e + pok_ports[pid].off_b);
00049    }
00050 }
00051 
00052 pok_port_size_t pok_port_consumed_size (uint8_t pid)
00053 {
00054    if (pok_ports[pid].empty == TRUE)
00055    {
00056       return 0;
00057    }
00058 
00059    if (pok_ports[pid].off_b < pok_ports[pid].off_e )
00060    {
00061       return (pok_ports[pid].off_e - pok_ports[pid].off_b);
00062    }
00063    else
00064    {
00065       return (pok_ports[pid].size - pok_ports[pid].off_b + pok_ports[pid].off_e);
00066    }
00067 }
00068 
00069 
00070 pok_ret_t pok_port_get (const uint32_t pid, void *data, const pok_port_size_t size)
00071 {
00072 
00073 #ifdef POK_NEEDS_PORTS_QUEUEING
00074    pok_port_size_t tmp_size;
00075    pok_port_size_t tmp_size2;
00076 #endif
00077 
00078    switch (pok_ports[pid].kind)
00079    {
00080 
00081 #ifdef POK_NEEDS_PORTS_QUEUEING
00082       case POK_PORT_KIND_QUEUEING:
00083          if (pok_ports[pid].empty == TRUE)
00084          {
00085             return POK_ERRNO_EINVAL;
00086          }
00087 
00088          if (pok_ports[pid].size < size)
00089          {
00090             return POK_ERRNO_SIZE;
00091          }
00092 
00093          if ((pok_ports[pid].off_b + size) > pok_ports[pid].size)
00094          {
00095             tmp_size = pok_ports[pid].size - pok_ports[pid].off_b;
00096             memcpy (data, &pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_b], tmp_size);
00097             tmp_size2 = size - tmp_size;
00098             memcpy (data + tmp_size, &pok_queue.data[pok_ports[pid].index], tmp_size2);
00099          }
00100          else
00101          {
00102             memcpy (data, &pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_b], size);
00103          }
00104 
00105          pok_ports[pid].off_b = (pok_ports[pid].off_b + size) % pok_ports[pid].size;
00106 
00107          if (pok_ports[pid].off_b == pok_ports[pid].off_e)
00108          {
00109             pok_ports[pid].empty = TRUE;
00110             pok_ports[pid].full  = FALSE;
00111          }
00112 
00113          return POK_ERRNO_OK;
00114          break;
00115 #endif
00116 
00117 #ifdef POK_NEEDS_PORTS_SAMPLING
00118       case POK_PORT_KIND_SAMPLING:
00119          if (pok_ports[pid].empty == TRUE)
00120          {
00121             return POK_ERRNO_EMPTY;
00122          }
00123 
00124          if (size > pok_ports[pid].size)
00125          {
00126             return POK_ERRNO_SIZE;
00127          }
00128 
00129          memcpy (data, &pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_b], size);
00130 
00131          return POK_ERRNO_OK;
00132          break;
00133 #endif
00134 
00135       default:
00136          return POK_ERRNO_EINVAL;
00137    }
00138 }
00139 
00140 pok_ret_t  pok_port_write (const uint8_t pid, const void *data, const pok_port_size_t size)
00141 {
00142 #ifdef POK_NEEDS_PORTS_QUEUEING
00143    pok_port_size_t tmp_size;
00144    pok_port_size_t tmp_size2;
00145 #endif
00146 
00147    switch (pok_ports[pid].kind)
00148    {
00149 #ifdef POK_NEEDS_PORTS_QUEUEING
00150       case POK_PORT_KIND_QUEUEING:
00151          if (pok_ports[pid].full == TRUE)
00152          {
00153             return POK_ERRNO_SIZE;
00154          }
00155 
00156          if (size > pok_ports[pid].size)
00157          {
00158             return POK_ERRNO_SIZE;
00159          }
00160 
00161          if ((pok_ports[pid].off_e + size) > pok_ports[pid].size)
00162          {
00163             tmp_size = pok_ports[pid].size - pok_ports[pid].off_e;
00164             memcpy (&pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_e], data, tmp_size);
00165 
00166             tmp_size2 = size - tmp_size;
00167             memcpy (&pok_queue.data[pok_ports[pid].index], data + tmp_size, tmp_size2);
00168          }
00169          else
00170          {
00171             memcpy (&pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_e], data, size);
00172          }
00173 
00174          pok_ports[pid].off_e = (pok_ports[pid].off_e + size) % pok_ports[pid].size;
00175 
00176          if (pok_ports[pid].off_e == pok_ports[pid].off_b)
00177          {
00178             pok_ports[pid].full = TRUE;
00179          }
00180 
00181          pok_ports[pid].empty = FALSE;
00182 
00183          return POK_ERRNO_OK;
00184 
00185          break;
00186 #endif
00187 
00188 #ifdef POK_NEEDS_PORTS_SAMPLING
00189       case POK_PORT_KIND_SAMPLING:
00190 
00191          if (size > pok_ports[pid].size)
00192          {
00193             return POK_ERRNO_SIZE;
00194          }
00195 
00196          memcpy (&pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_e], data, size);
00197 
00198          pok_ports[pid].empty = FALSE;
00199          pok_ports[pid].last_receive = POK_GETTICK ();
00200 
00201          return POK_ERRNO_OK;
00202 
00203          break;
00204 #endif
00205 
00206       default:
00207          return POK_ERRNO_EINVAL;
00208    }
00209 }
00210 
00211 
00212 /*
00213  * This function is designed to transfer data from one port to another
00214  * It is called when we transfer all data from one partition to the
00215  * others.
00216  */
00217 pok_ret_t pok_port_transfer (const uint8_t pid_dst, const uint8_t pid_src)
00218 {
00219    pok_port_size_t len = 0;
00220    pok_port_size_t src_len_consumed = 0;
00221 
00222    if (pok_ports[pid_src].empty == TRUE)
00223    {
00224       return POK_ERRNO_EMPTY;
00225    }
00226 
00227    if (pok_ports[pid_src].kind == POK_PORT_KIND_QUEUEING)
00228    {
00229       len = pok_port_available_size (pid_dst);
00230    }
00231    else
00232    {
00233       if (pok_ports[pid_src].size != pok_ports[pid_dst].size)
00234       {
00235          return POK_ERRNO_SIZE;
00236       }
00237 
00238       len = pok_ports[pid_src].size;
00239    }
00240 
00241    if (pok_ports[pid_src].kind == POK_PORT_KIND_QUEUEING)
00242    {
00243       src_len_consumed = pok_port_consumed_size (pid_src);
00244 
00245       if (src_len_consumed == 0)
00246       {
00247          return POK_ERRNO_SIZE;
00248       }
00249 
00250       if (len > src_len_consumed)
00251       {
00252          len = src_len_consumed;
00253       }
00254       /*
00255        * Here, we check the size of data produced in the source port.
00256        * If there is more free space in the destination port, the size
00257        * of copied data will be the occupied size in the source port.
00258        */
00259    }
00260 
00261    if (len == 0)
00262    {
00263       return POK_ERRNO_SIZE;
00264    }
00265    /*
00266     * Len is the size to copy. If size is null, it's better to return
00267     * directly
00268     */
00269 
00270    memcpy (&pok_queue.data[pok_ports[pid_dst].index + pok_ports[pid_dst].off_e], &pok_queue.data[pok_ports[pid_src].index + pok_ports[pid_src].off_b], len);
00271 
00272    if (pok_ports[pid_src].kind == POK_PORT_KIND_QUEUEING)
00273    {
00274       pok_ports[pid_dst].off_e =  (pok_ports[pid_dst].off_e + len) % pok_ports[pid_dst].size;
00275       pok_ports[pid_src].off_b =  (pok_ports[pid_src].off_b + len) % pok_ports[pid_src].size;
00276 
00277       if (pok_ports[pid_src].off_b == pok_ports[pid_src].off_e)
00278       {
00279          pok_ports[pid_src].empty = TRUE;
00280          pok_ports[pid_src].full  = FALSE;
00281       }
00282    }
00283    else
00284    {
00285       pok_ports[pid_src].empty = TRUE;
00286    }
00287 
00288    pok_ports[pid_src].full  = FALSE;
00289    pok_ports[pid_dst].empty = FALSE;
00290 
00291    return POK_ERRNO_OK;
00292 }
00293 
00294 bool_t pok_own_port (const uint8_t partition, const uint8_t port)
00295 {
00296    if (port > POK_CONFIG_NB_PORTS)
00297    {
00298       return FALSE;
00299    }
00300 
00301 #ifdef POK_CONFIG_PARTITIONS_PORTS
00302    if ((((uint8_t[]) POK_CONFIG_PARTITIONS_PORTS)[port]) == partition)
00303    {
00304       return TRUE;
00305    }
00306 #endif
00307 
00308    return FALSE;
00309 }
00310 
00311 #endif