libspe2  0.9a
mbox.c
Go to the documentation of this file.
1 /*
2  * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
3  * Copyright (C) 2005 IBM Corp.
4  *
5  * This library is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation; either version 2.1 of the License,
8  * or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13  * License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <poll.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 
26 #include "create.h"
27 #include "mbox.h"
28 
34 static __inline__ int _base_spe_out_mbox_read_ps(spe_context_ptr_t spectx,
35  unsigned int mbox_data[],
36  int count)
37 {
38  volatile struct spe_spu_control_area *cntl_area =
40  int total;
41  int entries;
42 
44  total = 0;
45  while (total < count) {
46  entries = cntl_area->SPU_Mbox_Stat & 0xFF;
47  if (entries == 0) break; // no entries
48  if (entries > count - total) entries = count - total; // don't read more than we need;
49  while(entries--) {
50  mbox_data[total] = cntl_area->SPU_Out_Mbox;
51  total ++;
52  }
53  }
55  return total;
56 }
57 
59  unsigned int mbox_data[],
60  int count)
61 {
62  int rc;
63 
64  if (mbox_data == NULL || count < 1){
65  errno = EINVAL;
66  return -1;
67  }
68 
69  if (spectx->base_private->flags & SPE_MAP_PS) {
70  rc = _base_spe_out_mbox_read_ps(spectx, mbox_data, count);
71  } else {
72  rc = read(_base_spe_open_if_closed(spectx,FD_MBOX, 0), mbox_data, count*4);
73  DEBUG_PRINTF("%s read rc: %d\n", __FUNCTION__, rc);
74  if (rc != -1) {
75  rc /= 4;
76  } else {
77  if (errno == EAGAIN ) { // no data ready to be read
78  errno = 0;
79  rc = 0;
80  }
81  }
82  }
83  return rc;
84 }
85 
86 static __inline__ int _base_spe_in_mbox_write_ps(spe_context_ptr_t spectx,
87  unsigned int *mbox_data,
88  int count)
89 {
90  volatile struct spe_spu_control_area *cntl_area =
92  int total = 0;
93  unsigned int *aux;
94  int space;
95 
97  aux = mbox_data;
98  while (total < count) {
99  space = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF;
100  if (space == 0) break; // no space
101  if (space > count - total) space = count - total; // don't write more than we have
102  while (space --) {
103  cntl_area->SPU_In_Mbox = *aux++;
104  total++;
105  }
106  }
108 
109  return total;
110 }
111 
113  unsigned int *mbox_data,
114  int count,
115  int behavior_flag)
116 {
117  int rc;
118  int total;
119  unsigned int *aux;
120  struct pollfd fds;
121 
122  if (mbox_data == NULL || count < 1){
123  errno = EINVAL;
124  return -1;
125  }
126 
127  switch (behavior_flag) {
128  case SPE_MBOX_ALL_BLOCKING: // write all, even if blocking
129  total = rc = 0;
130  if (spectx->base_private->flags & SPE_MAP_PS) {
131  do {
132  aux = mbox_data + total;
133  total += _base_spe_in_mbox_write_ps(spectx, aux, count - total);
134  if (total < count) { // we could not write everything, wait for space
135  fds.fd = _base_spe_open_if_closed(spectx, FD_WBOX, 0);
136  fds.events = POLLOUT;
137  rc = poll(&fds, 1, -1);
138  if (rc == -1 )
139  return -1;
140  }
141  } while (total < count);
142  } else {
143  while (total < 4*count) {
144  rc = write(_base_spe_open_if_closed(spectx,FD_WBOX, 0),
145  (const char *)mbox_data + total, 4*count - total);
146  if (rc == -1) {
147  break;
148  }
149  total += rc;
150  }
151  total /=4;
152  }
153  break;
154 
155  case SPE_MBOX_ANY_BLOCKING: // write at least one, even if blocking
156  total = rc = 0;
157  if (spectx->base_private->flags & SPE_MAP_PS) {
158  do {
159  total = _base_spe_in_mbox_write_ps(spectx, mbox_data, count);
160  if (total == 0) { // we could not anything, wait for space
161  fds.fd = _base_spe_open_if_closed(spectx, FD_WBOX, 0);
162  fds.events = POLLOUT;
163  rc = poll(&fds, 1, -1);
164  if (rc == -1 )
165  return -1;
166  }
167  } while (total == 0);
168  } else {
169  rc = write(_base_spe_open_if_closed(spectx,FD_WBOX, 0), mbox_data, 4*count);
170  total = rc/4;
171  }
172  break;
173 
174  case SPE_MBOX_ANY_NONBLOCKING: // only write, if non blocking
175  total = rc = 0;
176  // write directly if we map the PS else write via spufs
177  if (spectx->base_private->flags & SPE_MAP_PS) {
178  total = _base_spe_in_mbox_write_ps(spectx, mbox_data, count);
179  } else {
180  rc = write(_base_spe_open_if_closed(spectx,FD_WBOX_NB, 0), mbox_data, 4*count);
181  if (rc == -1 && errno == EAGAIN) {
182  rc = 0;
183  errno = 0;
184  }
185  total = rc/4;
186  }
187  break;
188 
189  default:
190  errno = EINVAL;
191  return -1;
192  }
193 
194  if (rc == -1) {
195  errno = EIO;
196  return -1;
197  }
198 
199  return total;
200 }
201 
203 {
204  int rc, ret;
205  volatile struct spe_spu_control_area *cntl_area =
206  spectx->base_private->cntl_mmap_base;
207 
208  if (spectx->base_private->flags & SPE_MAP_PS) {
209  ret = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF;
210  } else {
211  rc = read(_base_spe_open_if_closed(spectx,FD_WBOX_STAT, 0), &ret, 4);
212  if (rc != 4)
213  ret = -1;
214  }
215 
216  return ret;
217 
218 }
219 
221 {
222  int rc, ret;
223  volatile struct spe_spu_control_area *cntl_area =
224  spectx->base_private->cntl_mmap_base;
225 
226  if (spectx->base_private->flags & SPE_MAP_PS) {
227  ret = cntl_area->SPU_Mbox_Stat & 0xFF;
228  } else {
229  rc = read(_base_spe_open_if_closed(spectx,FD_MBOX_STAT, 0), &ret, 4);
230  if (rc != 4)
231  ret = -1;
232  }
233 
234  return ret;
235 
236 }
237 
239 {
240  int rc, ret;
241  volatile struct spe_spu_control_area *cntl_area =
242  spectx->base_private->cntl_mmap_base;
243 
244  if (spectx->base_private->flags & SPE_MAP_PS) {
245  ret = (cntl_area->SPU_Mbox_Stat >> 16) & 0xFF;
246  } else {
247  rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_STAT, 0), &ret, 4);
248  if (rc != 4)
249  ret = -1;
250 
251  }
252  return ret;
253 }
254 
256  unsigned int mbox_data[],
257  int count,
258  int behavior_flag)
259 {
260  int rc;
261  int total;
262 
263  if (mbox_data == NULL || count < 1){
264  errno = EINVAL;
265  return -1;
266  }
267 
268  switch (behavior_flag) {
269  case SPE_MBOX_ALL_BLOCKING: // read all, even if blocking
270  total = rc = 0;
271  while (total < 4*count) {
272  rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0),
273  (char *)mbox_data + total, 4*count - total);
274  if (rc == -1) {
275  break;
276  }
277  total += rc;
278  }
279  break;
280 
281  case SPE_MBOX_ANY_BLOCKING: // read at least one, even if blocking
282  total = rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0), mbox_data, 4*count);
283  break;
284 
285  case SPE_MBOX_ANY_NONBLOCKING: // only reaad, if non blocking
286  rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_NB, 0), mbox_data, 4*count);
287  if (rc == -1 && errno == EAGAIN) {
288  rc = 0;
289  errno = 0;
290  }
291  total = rc;
292  break;
293 
294  default:
295  errno = EINVAL;
296  return -1;
297  }
298 
299  if (rc == -1) {
300  errno = EIO;
301  return -1;
302  }
303 
304  return rc / 4;
305 }
306 
308  unsigned int signal_reg,
309  unsigned int data )
310 {
311  int rc;
312 
313  if (spectx->base_private->flags & SPE_MAP_PS) {
314  if (signal_reg == SPE_SIG_NOTIFY_REG_1) {
316 
317  sig->SPU_Sig_Notify_1 = data;
318  } else if (signal_reg == SPE_SIG_NOTIFY_REG_2) {
320 
321  sig->SPU_Sig_Notify_2 = data;
322  } else {
323  errno = EINVAL;
324  return -1;
325  }
326  rc = 0;
327  } else {
328  if (signal_reg == SPE_SIG_NOTIFY_REG_1)
329  rc = write(_base_spe_open_if_closed(spectx,FD_SIG1, 0), &data, 4);
330  else if (signal_reg == SPE_SIG_NOTIFY_REG_2)
331  rc = write(_base_spe_open_if_closed(spectx,FD_SIG2, 0), &data, 4);
332  else {
333  errno = EINVAL;
334  return -1;
335  }
336 
337  if (rc == 4)
338  rc = 0;
339 
340  if (signal_reg == SPE_SIG_NOTIFY_REG_1)
342  else if (signal_reg == SPE_SIG_NOTIFY_REG_2)
344  }
345 
346  return rc;
347 }
348 
349 
350