libspe2 0.9a
|
00001 /* 00002 * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS 00003 * Copyright (C) 2005 IBM Corp. 00004 * 00005 * This library is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 2.1 of the License, 00008 * or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, but 00011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this library; if not, write to the Free Software Foundation, 00017 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #include <errno.h> 00021 #include <fcntl.h> 00022 #include <poll.h> 00023 #include <stdio.h> 00024 #include <unistd.h> 00025 00026 #include "create.h" 00027 #include "mbox.h" 00028 00034 static __inline__ int _base_spe_out_mbox_read_ps(spe_context_ptr_t spectx, 00035 unsigned int mbox_data[], 00036 int count) 00037 { 00038 volatile struct spe_spu_control_area *cntl_area = 00039 spectx->base_private->cntl_mmap_base; 00040 int total; 00041 int entries; 00042 00043 _base_spe_context_lock(spectx, FD_MBOX); 00044 total = 0; 00045 while (total < count) { 00046 entries = cntl_area->SPU_Mbox_Stat & 0xFF; 00047 if (entries == 0) break; // no entries 00048 if (entries > count - total) entries = count - total; // don't read more than we need; 00049 while(entries--) { 00050 mbox_data[total] = cntl_area->SPU_Out_Mbox; 00051 total ++; 00052 } 00053 } 00054 _base_spe_context_unlock(spectx, FD_MBOX); 00055 return total; 00056 } 00057 00058 int _base_spe_out_mbox_read(spe_context_ptr_t spectx, 00059 unsigned int mbox_data[], 00060 int count) 00061 { 00062 int rc; 00063 00064 if (mbox_data == NULL || count < 1){ 00065 errno = EINVAL; 00066 return -1; 00067 } 00068 00069 if (spectx->base_private->flags & SPE_MAP_PS) { 00070 rc = _base_spe_out_mbox_read_ps(spectx, mbox_data, count); 00071 } else { 00072 rc = read(_base_spe_open_if_closed(spectx,FD_MBOX, 0), mbox_data, count*4); 00073 DEBUG_PRINTF("%s read rc: %d\n", __FUNCTION__, rc); 00074 if (rc != -1) { 00075 rc /= 4; 00076 } else { 00077 if (errno == EAGAIN ) { // no data ready to be read 00078 errno = 0; 00079 rc = 0; 00080 } 00081 } 00082 } 00083 return rc; 00084 } 00085 00086 static __inline__ int _base_spe_in_mbox_write_ps(spe_context_ptr_t spectx, 00087 unsigned int *mbox_data, 00088 int count) 00089 { 00090 volatile struct spe_spu_control_area *cntl_area = 00091 spectx->base_private->cntl_mmap_base; 00092 int total = 0; 00093 unsigned int *aux; 00094 int space; 00095 00096 _base_spe_context_lock(spectx, FD_WBOX); 00097 aux = mbox_data; 00098 while (total < count) { 00099 space = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF; 00100 if (space == 0) break; // no space 00101 if (space > count - total) space = count - total; // don't write more than we have 00102 while (space --) { 00103 cntl_area->SPU_In_Mbox = *aux++; 00104 total++; 00105 } 00106 } 00107 _base_spe_context_unlock(spectx, FD_WBOX); 00108 00109 return total; 00110 } 00111 00112 int _base_spe_in_mbox_write(spe_context_ptr_t spectx, 00113 unsigned int *mbox_data, 00114 int count, 00115 int behavior_flag) 00116 { 00117 int rc; 00118 int total; 00119 unsigned int *aux; 00120 struct pollfd fds; 00121 00122 if (mbox_data == NULL || count < 1){ 00123 errno = EINVAL; 00124 return -1; 00125 } 00126 00127 switch (behavior_flag) { 00128 case SPE_MBOX_ALL_BLOCKING: // write all, even if blocking 00129 total = rc = 0; 00130 if (spectx->base_private->flags & SPE_MAP_PS) { 00131 do { 00132 aux = mbox_data + total; 00133 total += _base_spe_in_mbox_write_ps(spectx, aux, count - total); 00134 if (total < count) { // we could not write everything, wait for space 00135 fds.fd = _base_spe_open_if_closed(spectx, FD_WBOX, 0); 00136 fds.events = POLLOUT; 00137 rc = poll(&fds, 1, -1); 00138 if (rc == -1 ) 00139 return -1; 00140 } 00141 } while (total < count); 00142 } else { 00143 while (total < 4*count) { 00144 rc = write(_base_spe_open_if_closed(spectx,FD_WBOX, 0), 00145 (const char *)mbox_data + total, 4*count - total); 00146 if (rc == -1) { 00147 break; 00148 } 00149 total += rc; 00150 } 00151 total /=4; 00152 } 00153 break; 00154 00155 case SPE_MBOX_ANY_BLOCKING: // write at least one, even if blocking 00156 total = rc = 0; 00157 if (spectx->base_private->flags & SPE_MAP_PS) { 00158 do { 00159 total = _base_spe_in_mbox_write_ps(spectx, mbox_data, count); 00160 if (total == 0) { // we could not anything, wait for space 00161 fds.fd = _base_spe_open_if_closed(spectx, FD_WBOX, 0); 00162 fds.events = POLLOUT; 00163 rc = poll(&fds, 1, -1); 00164 if (rc == -1 ) 00165 return -1; 00166 } 00167 } while (total == 0); 00168 } else { 00169 rc = write(_base_spe_open_if_closed(spectx,FD_WBOX, 0), mbox_data, 4*count); 00170 total = rc/4; 00171 } 00172 break; 00173 00174 case SPE_MBOX_ANY_NONBLOCKING: // only write, if non blocking 00175 total = rc = 0; 00176 // write directly if we map the PS else write via spufs 00177 if (spectx->base_private->flags & SPE_MAP_PS) { 00178 total = _base_spe_in_mbox_write_ps(spectx, mbox_data, count); 00179 } else { 00180 rc = write(_base_spe_open_if_closed(spectx,FD_WBOX_NB, 0), mbox_data, 4*count); 00181 if (rc == -1 && errno == EAGAIN) { 00182 rc = 0; 00183 errno = 0; 00184 } 00185 total = rc/4; 00186 } 00187 break; 00188 00189 default: 00190 errno = EINVAL; 00191 return -1; 00192 } 00193 00194 if (rc == -1) { 00195 errno = EIO; 00196 return -1; 00197 } 00198 00199 return total; 00200 } 00201 00202 int _base_spe_in_mbox_status(spe_context_ptr_t spectx) 00203 { 00204 int rc, ret; 00205 volatile struct spe_spu_control_area *cntl_area = 00206 spectx->base_private->cntl_mmap_base; 00207 00208 if (spectx->base_private->flags & SPE_MAP_PS) { 00209 ret = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF; 00210 } else { 00211 rc = read(_base_spe_open_if_closed(spectx,FD_WBOX_STAT, 0), &ret, 4); 00212 if (rc != 4) 00213 ret = -1; 00214 } 00215 00216 return ret; 00217 00218 } 00219 00220 int _base_spe_out_mbox_status(spe_context_ptr_t spectx) 00221 { 00222 int rc, ret; 00223 volatile struct spe_spu_control_area *cntl_area = 00224 spectx->base_private->cntl_mmap_base; 00225 00226 if (spectx->base_private->flags & SPE_MAP_PS) { 00227 ret = cntl_area->SPU_Mbox_Stat & 0xFF; 00228 } else { 00229 rc = read(_base_spe_open_if_closed(spectx,FD_MBOX_STAT, 0), &ret, 4); 00230 if (rc != 4) 00231 ret = -1; 00232 } 00233 00234 return ret; 00235 00236 } 00237 00238 int _base_spe_out_intr_mbox_status(spe_context_ptr_t spectx) 00239 { 00240 int rc, ret; 00241 volatile struct spe_spu_control_area *cntl_area = 00242 spectx->base_private->cntl_mmap_base; 00243 00244 if (spectx->base_private->flags & SPE_MAP_PS) { 00245 ret = (cntl_area->SPU_Mbox_Stat >> 16) & 0xFF; 00246 } else { 00247 rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_STAT, 0), &ret, 4); 00248 if (rc != 4) 00249 ret = -1; 00250 00251 } 00252 return ret; 00253 } 00254 00255 int _base_spe_out_intr_mbox_read(spe_context_ptr_t spectx, 00256 unsigned int mbox_data[], 00257 int count, 00258 int behavior_flag) 00259 { 00260 int rc; 00261 int total; 00262 00263 if (mbox_data == NULL || count < 1){ 00264 errno = EINVAL; 00265 return -1; 00266 } 00267 00268 switch (behavior_flag) { 00269 case SPE_MBOX_ALL_BLOCKING: // read all, even if blocking 00270 total = rc = 0; 00271 while (total < 4*count) { 00272 rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0), 00273 (char *)mbox_data + total, 4*count - total); 00274 if (rc == -1) { 00275 break; 00276 } 00277 total += rc; 00278 } 00279 break; 00280 00281 case SPE_MBOX_ANY_BLOCKING: // read at least one, even if blocking 00282 total = rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0), mbox_data, 4*count); 00283 break; 00284 00285 case SPE_MBOX_ANY_NONBLOCKING: // only reaad, if non blocking 00286 rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_NB, 0), mbox_data, 4*count); 00287 if (rc == -1 && errno == EAGAIN) { 00288 rc = 0; 00289 errno = 0; 00290 } 00291 total = rc; 00292 break; 00293 00294 default: 00295 errno = EINVAL; 00296 return -1; 00297 } 00298 00299 if (rc == -1) { 00300 errno = EIO; 00301 return -1; 00302 } 00303 00304 return rc / 4; 00305 } 00306 00307 int _base_spe_signal_write(spe_context_ptr_t spectx, 00308 unsigned int signal_reg, 00309 unsigned int data ) 00310 { 00311 int rc; 00312 00313 if (spectx->base_private->flags & SPE_MAP_PS) { 00314 if (signal_reg == SPE_SIG_NOTIFY_REG_1) { 00315 spe_sig_notify_1_area_t *sig = spectx->base_private->signal1_mmap_base; 00316 00317 sig->SPU_Sig_Notify_1 = data; 00318 } else if (signal_reg == SPE_SIG_NOTIFY_REG_2) { 00319 spe_sig_notify_2_area_t *sig = spectx->base_private->signal2_mmap_base; 00320 00321 sig->SPU_Sig_Notify_2 = data; 00322 } else { 00323 errno = EINVAL; 00324 return -1; 00325 } 00326 rc = 0; 00327 } else { 00328 if (signal_reg == SPE_SIG_NOTIFY_REG_1) 00329 rc = write(_base_spe_open_if_closed(spectx,FD_SIG1, 0), &data, 4); 00330 else if (signal_reg == SPE_SIG_NOTIFY_REG_2) 00331 rc = write(_base_spe_open_if_closed(spectx,FD_SIG2, 0), &data, 4); 00332 else { 00333 errno = EINVAL; 00334 return -1; 00335 } 00336 00337 if (rc == 4) 00338 rc = 0; 00339 00340 if (signal_reg == SPE_SIG_NOTIFY_REG_1) 00341 _base_spe_close_if_open(spectx,FD_SIG1); 00342 else if (signal_reg == SPE_SIG_NOTIFY_REG_2) 00343 _base_spe_close_if_open(spectx,FD_SIG2); 00344 } 00345 00346 return rc; 00347 } 00348 00349 00350