00001 #include <string.h>
00002 #include <stdio.h>
00003 #include <spu_mfcio.h>
00004
00005 #include <moc.h>
00006 #include <spu/moc_datatype_spu.h>
00007 #include <internal/imoc.h>
00008 #include <internal/imoc_macros.h>
00009 #include <internal/spu/imoc_dma_spu.h>
00010 #include <internal/spu/imoc_core_spu.h>
00011
00012 int MOC_Recv(void* buf, int count, MOC_Datatype datatype, int source, int tag,
00013 MOC_Comm comm, MOC_Status *status)
00014 {
00015
00016 moc_message_envelope_t* sourceQueueEntry;
00017 moc_message_status_t sourceMessageStatus __attribute__((__aligned__(16)));
00018 unsigned int tag_id;
00019 int bytecount, err;
00020
00021 err = 0;
00022 if (((datatype & 0xF0) >> 4) == 0)
00023 bytecount = count;
00024 else
00025 bytecount = count * (((datatype & 0xF0) >> 4) * 2);
00026
00027 status->MOC_SOURCE = source;
00028 status->message_size = bytecount;
00029
00030 IMOC_TEST_PROC_NULL(source)
00031 IMOC_TEST_PROC_SELF(source)
00032 IMOC_TEST_BYTECOUNT(bytecount)
00033
00034 if (bytecount != 0)
00035 {
00036 IMOC_TEST_BUFFER(buf)
00037 }
00038 IMOC_TEST_RANK_RECV(source)
00039 IMOC_TEST_TAG_RECV(tag)
00040 IMOC_TEST_COMM_RECV(comm)
00041
00042
00043 sourceQueueEntry = NULL;
00044 while (sourceQueueEntry == NULL)
00045 {
00046 sourceQueueEntry = IMOC_get_entry(source, tag, comm, 0, status);
00047 }
00048
00049 status->MOC_TAG = tag;
00050 status->mid = sourceQueueEntry->id;
00051
00052
00053 if (sourceQueueEntry->datatype != datatype && sourceQueueEntry->datatype
00054 !=MOC_BYTE && datatype != MOC_BYTE)
00055 {
00056 status->MOC_ERROR = MOC_ERR_TYPE;
00057 return MOC_ERR_TYPE;
00058 }
00059
00060
00061 if (sourceQueueEntry->flags.bits.channel == IMOC_MESSAGE_CHANNEL_ENV)
00062 {
00063
00064 memcpy(buf, &sourceQueueEntry->message_address, (bytecount
00065 < sourceQueueEntry->size) ? bytecount : sourceQueueEntry->size);
00066 }
00067 else
00068 if (sourceQueueEntry->flags.bits.channel == IMOC_MESSAGE_CHANNEL_DMA)
00069 {
00070 if (bytecount != 0)
00071 {
00072 IMOC_TEST_ALIGNMENT(buf)
00073 }
00074
00075 err = IMOC_get_data(buf, sourceQueueEntry->message_address,
00076 bytecount);
00077 if (err)
00078 {
00079 return err;
00080 }
00081 }
00082 else
00083 {
00084
00085 status->MOC_ERROR = MOC_ERR_INTERN;
00086 return MOC_ERR_INTERN;
00087 }
00088
00089
00090 if (sourceQueueEntry->flags.bits.signal_back == 1)
00091 {
00092
00093 sourceMessageStatus.buffer_offset = 0;
00094 sourceMessageStatus.flags.value = 0;
00095 if (sourceQueueEntry->flags.bits.keep_valid)
00096 sourceMessageStatus.flags.bits.valid = 1;
00097
00098
00099 if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID)
00100 return MOC_ERR_INTERN;
00101 mfc_put(
00102 &sourceMessageStatus,
00103 IMOC_EA_REMOTE_STATUS_ENTRY(sourceQueueEntry->id,status->MOC_SOURCE),
00104 sizeof(moc_message_status_t), tag_id, 0, 0);
00105 mfc_write_tag_mask(1 << tag_id);
00106 mfc_read_tag_status_all();
00107 mfc_tag_release(tag_id);
00108
00109 }
00110 sourceQueueEntry->flags.value = 0;
00111
00112 status->MOC_ERROR = 0;
00113 return 0;
00114 }