POK(kernelpart)
portutils.c
Go to the documentation of this file.
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Thu Jan 15 23:34:13 2009
15  */
16 
24 #if defined (POK_NEEDS_PORTS_SAMPLING) || defined (POK_NEEDS_PORTS_QUEUEING)
25 #include <types.h>
26 #include <libc.h>
27 #include <core/time.h>
28 #include <middleware/port.h>
29 #include <middleware/queue.h>
30 
31 extern pok_port_t pok_ports[POK_CONFIG_NB_PORTS];
32 extern pok_queue_t pok_queue;
33 extern uint8_t pok_current_partition;
34 
35 pok_port_size_t pok_port_available_size (uint8_t pid)
36 {
37  if (pok_ports[pid].full == TRUE)
38  {
39  return 0;
40  }
41 
42  if (pok_ports[pid].off_b < pok_ports[pid].off_e)
43  {
44  return (pok_ports[pid].off_b - pok_ports[pid].off_e);
45  }
46  else
47  {
48  return (pok_ports[pid].size - pok_ports[pid].off_e + pok_ports[pid].off_b);
49  }
50 }
51 
52 pok_port_size_t pok_port_consumed_size (uint8_t pid)
53 {
54  if (pok_ports[pid].empty == TRUE)
55  {
56  return 0;
57  }
58 
59  if (pok_ports[pid].off_b < pok_ports[pid].off_e )
60  {
61  return (pok_ports[pid].off_e - pok_ports[pid].off_b);
62  }
63  else
64  {
65  return (pok_ports[pid].size - pok_ports[pid].off_b + pok_ports[pid].off_e);
66  }
67 }
68 
69 
70 pok_ret_t pok_port_get (const uint32_t pid, void *data, const pok_port_size_t size)
71 {
72 
73 #ifdef POK_NEEDS_PORTS_QUEUEING
74  pok_port_size_t tmp_size;
75  pok_port_size_t tmp_size2;
76 #endif
77 
78  switch (pok_ports[pid].kind)
79  {
80 
81 #ifdef POK_NEEDS_PORTS_QUEUEING
83  if (pok_ports[pid].empty == TRUE)
84  {
85  return POK_ERRNO_EINVAL;
86  }
87 
88  if (pok_ports[pid].size < size)
89  {
90  return POK_ERRNO_SIZE;
91  }
92 
93  if ((pok_ports[pid].off_b + size) > pok_ports[pid].size)
94  {
95  tmp_size = pok_ports[pid].size - pok_ports[pid].off_b;
96  memcpy (data, &pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_b], tmp_size);
97  tmp_size2 = size - tmp_size;
98  memcpy (data + tmp_size, &pok_queue.data[pok_ports[pid].index], tmp_size2);
99  }
100  else
101  {
102  memcpy (data, &pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_b], size);
103  }
104 
105  pok_ports[pid].off_b = (pok_ports[pid].off_b + size) % pok_ports[pid].size;
106 
107  if (pok_ports[pid].off_b == pok_ports[pid].off_e)
108  {
109  pok_ports[pid].empty = TRUE;
110  pok_ports[pid].full = FALSE;
111  }
112 
113  return POK_ERRNO_OK;
114  break;
115 #endif
116 
117 #ifdef POK_NEEDS_PORTS_SAMPLING
119  if (pok_ports[pid].empty == TRUE)
120  {
121  return POK_ERRNO_EMPTY;
122  }
123 
124  if (size > pok_ports[pid].size)
125  {
126  return POK_ERRNO_SIZE;
127  }
128 
129  memcpy (data, &pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_b], size);
130 
131  return POK_ERRNO_OK;
132  break;
133 #endif
134 
135  default:
136  return POK_ERRNO_EINVAL;
137  }
138 }
139 
140 pok_ret_t pok_port_write (const uint8_t pid, const void *data, const pok_port_size_t size)
141 {
142 #ifdef POK_NEEDS_PORTS_QUEUEING
143  pok_port_size_t tmp_size;
144  pok_port_size_t tmp_size2;
145 #endif
146 
147  switch (pok_ports[pid].kind)
148  {
149 #ifdef POK_NEEDS_PORTS_QUEUEING
151  if (pok_ports[pid].full == TRUE)
152  {
153  return POK_ERRNO_SIZE;
154  }
155 
156  if (size > pok_ports[pid].size)
157  {
158  return POK_ERRNO_SIZE;
159  }
160 
161  if ((pok_ports[pid].off_e + size) > pok_ports[pid].size)
162  {
163  tmp_size = pok_ports[pid].size - pok_ports[pid].off_e;
164  memcpy (&pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_e], data, tmp_size);
165 
166  tmp_size2 = size - tmp_size;
167  memcpy (&pok_queue.data[pok_ports[pid].index], data + tmp_size, tmp_size2);
168  }
169  else
170  {
171  memcpy (&pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_e], data, size);
172  }
173 
174  pok_ports[pid].off_e = (pok_ports[pid].off_e + size) % pok_ports[pid].size;
175 
176  if (pok_ports[pid].off_e == pok_ports[pid].off_b)
177  {
178  pok_ports[pid].full = TRUE;
179  }
180 
181  pok_ports[pid].empty = FALSE;
182 
183  return POK_ERRNO_OK;
184 
185  break;
186 #endif
187 
188 #ifdef POK_NEEDS_PORTS_SAMPLING
190 
191  if (size > pok_ports[pid].size)
192  {
193  return POK_ERRNO_SIZE;
194  }
195 
196  memcpy (&pok_queue.data[pok_ports[pid].index + pok_ports[pid].off_e], data, size);
197 
198  pok_ports[pid].empty = FALSE;
199  pok_ports[pid].last_receive = POK_GETTICK ();
200 
201  return POK_ERRNO_OK;
202 
203  break;
204 #endif
205 
206  default:
207  return POK_ERRNO_EINVAL;
208  }
209 }
210 
211 
212 /*
213  * This function is designed to transfer data from one port to another
214  * It is called when we transfer all data from one partition to the
215  * others.
216  */
217 pok_ret_t pok_port_transfer (const uint8_t pid_dst, const uint8_t pid_src)
218 {
219  pok_port_size_t len = 0;
220  pok_port_size_t src_len_consumed = 0;
221 
222  if (pok_ports[pid_src].empty == TRUE)
223  {
224  return POK_ERRNO_EMPTY;
225  }
226 
227  if (pok_ports[pid_src].kind == POK_PORT_KIND_QUEUEING)
228  {
229  len = pok_port_available_size (pid_dst);
230  }
231  else
232  {
233  if (pok_ports[pid_src].size != pok_ports[pid_dst].size)
234  {
235  return POK_ERRNO_SIZE;
236  }
237 
238  len = pok_ports[pid_src].size;
239  }
240 
241  if (pok_ports[pid_src].kind == POK_PORT_KIND_QUEUEING)
242  {
243  src_len_consumed = pok_port_consumed_size (pid_src);
244 
245  if (src_len_consumed == 0)
246  {
247  return POK_ERRNO_SIZE;
248  }
249 
250  if (len > src_len_consumed)
251  {
252  len = src_len_consumed;
253  }
254  /*
255  * Here, we check the size of data produced in the source port.
256  * If there is more free space in the destination port, the size
257  * of copied data will be the occupied size in the source port.
258  */
259  }
260 
261  if (len == 0)
262  {
263  return POK_ERRNO_SIZE;
264  }
265  /*
266  * Len is the size to copy. If size is null, it's better to return
267  * directly
268  */
269 
270  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);
271 
272  if (pok_ports[pid_src].kind == POK_PORT_KIND_QUEUEING)
273  {
274  pok_ports[pid_dst].off_e = (pok_ports[pid_dst].off_e + len) % pok_ports[pid_dst].size;
275  pok_ports[pid_src].off_b = (pok_ports[pid_src].off_b + len) % pok_ports[pid_src].size;
276 
277  if (pok_ports[pid_src].off_b == pok_ports[pid_src].off_e)
278  {
279  pok_ports[pid_src].empty = TRUE;
280  pok_ports[pid_src].full = FALSE;
281  }
282  }
283  else
284  {
285  pok_ports[pid_src].empty = TRUE;
286  }
287 
288  pok_ports[pid_src].full = FALSE;
289  pok_ports[pid_dst].empty = FALSE;
290 
291  return POK_ERRNO_OK;
292 }
293 
294 bool_t pok_own_port (const uint8_t partition, const uint8_t port)
295 {
296  if (port > POK_CONFIG_NB_PORTS)
297  {
298  return FALSE;
299  }
300 
301 #ifdef POK_CONFIG_PARTITIONS_PORTS
302  if ((((uint8_t[]) POK_CONFIG_PARTITIONS_PORTS)[port]) == partition)
303  {
304  return TRUE;
305  }
306 #endif
307 
308  return FALSE;
309 }
310 
311 #endif