00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <stdio.h>
00023 #include <stdint.h>
00024 #include <string.h>
00025 #include <unistd.h>
00026
00027 #include <sys/poll.h>
00028
00029 #include "create.h"
00030 #include "dma.h"
00031
00032 static int spe_read_tag_status_block(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status);
00033 static int spe_read_tag_status_noblock(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status);
00034
00035 static int issue_mfc_command(spe_context_ptr_t spectx, unsigned lsa, void *ea,
00036 unsigned size, unsigned tag, unsigned tid, unsigned rid,
00037 enum mfc_cmd cmd)
00038 {
00039 int ret;
00040
00041 DEBUG_PRINTF("queuing DMA %x %lx %x %x %x %x %x\n", lsa,
00042 (unsigned long)ea, size, tag, tid, rid, (unsigned)cmd);
00043
00044
00045 if (tag > 0x0f || tid > 0xff || rid > 0xff) {
00046 errno = EINVAL;
00047 return -1;
00048 }
00049
00050 if (spectx->base_private->flags & SPE_MAP_PS) {
00051 volatile struct spe_mfc_command_area *cmd_area =
00052 spectx->base_private->mfc_mmap_base;
00053 unsigned int eal = (uintptr_t) ea & 0xFFFFFFFF;
00054 unsigned int eah = (unsigned long long)(uintptr_t) ea >> 32;
00055 _base_spe_context_lock(spectx, FD_MFC);
00056 spectx->base_private->active_tagmask |= 1 << tag;
00057 DEBUG_PRINTF("set active tagmask = 0x%04x, tag=%i\n",spectx->base_private->active_tagmask,tag);
00058 while ((cmd_area->MFC_QStatus & 0x0000FFFF) == 0) ;
00059 do {
00060 cmd_area->MFC_LSA = lsa;
00061 cmd_area->MFC_EAH = eah;
00062 cmd_area->MFC_EAL = eal;
00063 cmd_area->MFC_Size_Tag = (size << 16) | tag;
00064 cmd_area->MFC_ClassID_CMD = (tid << 24) | (rid << 16) | cmd;
00065
00066 ret = cmd_area->MFC_CMDStatus & 0x00000003;
00067 } while (ret);
00068 _base_spe_context_unlock(spectx, FD_MFC);
00069 return 0;
00070 }
00071 else {
00072 int fd;
00073 fd = _base_spe_open_if_closed(spectx, FD_MFC, 0);
00074 if (fd != -1) {
00075 struct mfc_command_parameter_area parm = {
00076 .lsa = lsa,
00077 .ea = (unsigned long) ea,
00078 .size = size,
00079 .tag = tag,
00080 .class = (tid << 8) | rid,
00081 .cmd = cmd,
00082 };
00083 ret = write(fd, &parm, sizeof (parm));
00084 if ((ret < 0) && (errno != EIO)) {
00085 perror("spe_do_mfc_put: internal error");
00086 }
00087 return ret < 0 ? -1 : 0;
00088 }
00089 }
00090
00091 return 1;
00092 }
00093
00094 static int spe_do_mfc_put(spe_context_ptr_t spectx, unsigned src, void *dst,
00095 unsigned size, unsigned tag, unsigned tid, unsigned rid,
00096 enum mfc_cmd cmd)
00097 {
00098 int ret;
00099 ret = issue_mfc_command(spectx, src, dst, size, tag, tid, rid, cmd);
00100 if (ret <= 0) {
00101 return ret;
00102 }
00103 else {
00104
00105 memcpy(dst, spectx->base_private->mem_mmap_base + src, size);
00106 return 0;
00107 }
00108 }
00109
00110 static int spe_do_mfc_get(spe_context_ptr_t spectx, unsigned int dst, void *src,
00111 unsigned int size, unsigned int tag, unsigned tid, unsigned rid,
00112 enum mfc_cmd cmd)
00113 {
00114 int ret;
00115 ret = issue_mfc_command(spectx, dst, src, size, tag, tid, rid, cmd);
00116 if (ret <= 0) {
00117 return ret;
00118 }
00119 else {
00120
00121 memcpy(spectx->base_private->mem_mmap_base + dst, src, size);
00122 return 0;
00123 }
00124 }
00125
00126 int _base_spe_mfcio_put(spe_context_ptr_t spectx,
00127 unsigned int ls,
00128 void *ea,
00129 unsigned int size,
00130 unsigned int tag,
00131 unsigned int tid,
00132 unsigned int rid)
00133 {
00134 return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUT);
00135 }
00136
00137 int _base_spe_mfcio_putb(spe_context_ptr_t spectx,
00138 unsigned int ls,
00139 void *ea,
00140 unsigned int size,
00141 unsigned int tag,
00142 unsigned int tid,
00143 unsigned int rid)
00144 {
00145 return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTB);
00146 }
00147
00148 int _base_spe_mfcio_putf(spe_context_ptr_t spectx,
00149 unsigned int ls,
00150 void *ea,
00151 unsigned int size,
00152 unsigned int tag,
00153 unsigned int tid,
00154 unsigned int rid)
00155 {
00156 return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTF);
00157 }
00158
00159
00160 int _base_spe_mfcio_get(spe_context_ptr_t spectx,
00161 unsigned int ls,
00162 void *ea,
00163 unsigned int size,
00164 unsigned int tag,
00165 unsigned int tid,
00166 unsigned int rid)
00167 {
00168 return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GET);
00169 }
00170
00171 int _base_spe_mfcio_getb(spe_context_ptr_t spectx,
00172 unsigned int ls,
00173 void *ea,
00174 unsigned int size,
00175 unsigned int tag,
00176 unsigned int tid,
00177 unsigned int rid)
00178 {
00179 return spe_do_mfc_get(spectx, ls, ea, size, tag, rid, rid, MFC_CMD_GETB);
00180 }
00181
00182 int _base_spe_mfcio_getf(spe_context_ptr_t spectx,
00183 unsigned int ls,
00184 void *ea,
00185 unsigned int size,
00186 unsigned int tag,
00187 unsigned int tid,
00188 unsigned int rid)
00189 {
00190 return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GETF);
00191 }
00192
00193 static int spe_mfcio_tag_status_read_all(spe_context_ptr_t spectx,
00194 unsigned int mask, unsigned int *tag_status)
00195 {
00196 int fd;
00197
00198 if (spectx->base_private->flags & SPE_MAP_PS) {
00199 return spe_read_tag_status_block(spectx, mask, tag_status);
00200 } else {
00201 fd = _base_spe_open_if_closed(spectx, FD_MFC, 0);
00202 if (fd == -1) {
00203 return -1;
00204 }
00205
00206 if (fsync(fd) != 0) {
00207 return -1;
00208 }
00209
00210 return spe_read_tag_status_block(spectx, mask, tag_status);
00211 }
00212 }
00213
00214 static int spe_mfcio_tag_status_read_any(spe_context_ptr_t spectx,
00215 unsigned int mask, unsigned int *tag_status)
00216 {
00217 return spe_read_tag_status_block(spectx, mask, tag_status);
00218 }
00219
00220 static int spe_mfcio_tag_status_read_immediate(spe_context_ptr_t spectx,
00221 unsigned int mask, unsigned int *tag_status)
00222 {
00223 return spe_read_tag_status_noblock(spectx, mask, tag_status);
00224 }
00225
00226
00227
00228
00229
00230
00231 static int spe_read_tag_status_block(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status)
00232 {
00233 if (spectx->base_private->flags & SPE_MAP_PS) {
00234 volatile struct spe_mfc_command_area *cmd_area =
00235 spectx->base_private->mfc_mmap_base;
00236 _base_spe_context_lock(spectx, FD_MFC);
00237 cmd_area->Prxy_QueryMask = mask;
00238 __asm__ ("eieio");
00239 do {
00240 *tag_status = cmd_area->Prxy_TagStatus;
00241 spectx->base_private->active_tagmask ^= *tag_status;
00242 DEBUG_PRINTF("unset active tagmask = 0x%04x, tag_status = 0x%04x\n",
00243 spectx->base_private->active_tagmask,*tag_status);
00244 } while (*tag_status ^ mask);
00245 _base_spe_context_unlock(spectx, FD_MFC);
00246 return 0;
00247 } else {
00248 int fd;
00249 fd = _base_spe_open_if_closed(spectx, FD_MFC, 0);
00250 if (fd == -1) {
00251 return -1;
00252 }
00253
00254 if (read(fd,tag_status,4) == 4) {
00255 return 0;
00256 }
00257 }
00258 return -1;
00259 }
00260
00261 static int spe_read_tag_status_noblock(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status)
00262 {
00263 unsigned int ret;
00264
00265 if (spectx->base_private->flags & SPE_MAP_PS) {
00266 volatile struct spe_mfc_command_area *cmd_area =
00267 spectx->base_private->mfc_mmap_base;
00268
00269 _base_spe_context_lock(spectx, FD_MFC);
00270 cmd_area->Prxy_QueryMask = mask;
00271 __asm__ ("eieio");
00272 *tag_status = cmd_area->Prxy_TagStatus;
00273 spectx->base_private->active_tagmask ^= *tag_status;
00274 DEBUG_PRINTF("unset active tagmask = 0x%04x, tag_status = 0x%04x\n",
00275 spectx->base_private->active_tagmask,*tag_status);
00276 _base_spe_context_unlock(spectx, FD_MFC);
00277 return 0;
00278 } else {
00279 struct pollfd poll_fd;
00280 int fd;
00281
00282 fd = _base_spe_open_if_closed(spectx, FD_MFC, 0);
00283 if (fd == -1) {
00284 return -1;
00285 }
00286
00287 poll_fd.fd = fd;
00288 poll_fd.events = POLLIN;
00289
00290 ret = poll(&poll_fd, 1, 0);
00291
00292 if (ret < 0)
00293 return -1;
00294
00295 if (ret == 0 || !(poll_fd.revents & POLLIN)) {
00296 *tag_status = 0;
00297 return 0;
00298 }
00299
00300 if (read(fd,tag_status,4) == 4) {
00301 return 0;
00302 }
00303 }
00304 return -1;
00305 }
00306
00307 int _base_spe_mfcio_tag_status_read(spe_context_ptr_t spectx, unsigned int mask, unsigned int behavior, unsigned int *tag_status)
00308 {
00309 if ( mask != 0 ) {
00310 if (!(spectx->base_private->flags & SPE_MAP_PS))
00311 mask = 0;
00312 } else {
00313 if ((spectx->base_private->flags & SPE_MAP_PS))
00314 mask = spectx->base_private->active_tagmask;
00315 }
00316
00317 if (!tag_status) {
00318 errno = EINVAL;
00319 return -1;
00320 }
00321
00322 switch (behavior) {
00323 case SPE_TAG_ALL:
00324 return spe_mfcio_tag_status_read_all(spectx, mask, tag_status);
00325 case SPE_TAG_ANY:
00326 return spe_mfcio_tag_status_read_any(spectx, mask, tag_status);
00327 case SPE_TAG_IMMEDIATE:
00328 return spe_mfcio_tag_status_read_immediate(spectx, mask, tag_status);
00329 default:
00330 errno = EINVAL;
00331 return -1;
00332 }
00333 }
00334
00335 int _base_spe_mssync_start(spe_context_ptr_t spectx)
00336 {
00337 int ret, fd;
00338 unsigned int data = 1;
00339
00340 volatile struct spe_mssync_area *mss_area =
00341 spectx->base_private->mssync_mmap_base;
00342
00343 if (spectx->base_private->flags & SPE_MAP_PS) {
00344 mss_area->MFC_MSSync = data;
00345 return 0;
00346 } else {
00347 fd = _base_spe_open_if_closed(spectx, FD_MSS, 0);
00348 if (fd != -1) {
00349 ret = write(fd, &data, sizeof (data));
00350 if ((ret < 0) && (errno != EIO)) {
00351 perror("spe_mssync_start: internal error");
00352 }
00353 return ret < 0 ? -1 : 0;
00354 } else
00355 return -1;
00356 }
00357 }
00358
00359 int _base_spe_mssync_status(spe_context_ptr_t spectx)
00360 {
00361 int ret, fd;
00362 unsigned int data;
00363
00364 volatile struct spe_mssync_area *mss_area =
00365 spectx->base_private->mssync_mmap_base;
00366
00367 if (spectx->base_private->flags & SPE_MAP_PS) {
00368 return mss_area->MFC_MSSync;
00369 } else {
00370 fd = _base_spe_open_if_closed(spectx, FD_MSS, 0);
00371 if (fd != -1) {
00372 ret = read(fd, &data, sizeof (data));
00373 if ((ret < 0) && (errno != EIO)) {
00374 perror("spe_mssync_start: internal error");
00375 }
00376 return ret < 0 ? -1 : data;
00377 } else
00378 return -1;
00379 }
00380 }
00381
00382