/* * ======== process ======== * This is the stub-implementation for the process method */ static XDAS_Int32 process(ISCALE_Handle h, XDAS_Int8 *inBuf, XDAS_Int8 *outBuf, ISCALE_InArgs *inArgs, ISCALE_OutArgs *outArgs) { XDAS_Int32 retVal; VISA_Handle visa = (VISA_Handle)h; _SCALE_Msg *msg; /* get a message appropriate for this algorithm */ if ((msg = (_SCALE_Msg *)VISA_allocMsg(visa)) == NULL) { return (SCALE_ERUNTIME); } /* Specify the processing command that the skeleton should do */ msg->visa.cmd = _SCALE_CPROCESS; /* inBuf is a pointer, so we have to convert it */ msg->cmd.process.inBuf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(inBuf, inArgs->inBufSize, NULL); if (msg->cmd.process.inBuf == NULL) { retVal = SCALE_ERUNTIME; goto exit; } /* Similarly with outBuf. Note that inArgs and outArgs contain no * pointers, so we can simply copy the entire original structure. */ msg->cmd.process.outBuf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(outBuf, inArgs->outBufSize, NULL); if (msg->cmd.process.outBuf == NULL) { retVal = SCALE_ERUNTIME; goto exit; } /* inArgs has no pointers, so simply copy the struct fields into the msg */ msg->cmd.process.inArgs = *inArgs; /* Note that outArgs is *output* and need not be provided to the skel */ /* send the message to the skeleton and wait for completion */ retVal = VISA_call(visa, (VISA_Msg *)&msg); /* copy out the outArgs */ *outArgs = msg->cmd.process.outArgs; /* Note that we need not copy inArgs out of the msg. */ /* * Note that we don't have to do any reverse address translation, as the * originally provided buffers haven't changed. */ exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
static int copySparseSingleBufDescArrayWithV2P(XDM1_SingleBufDesc *pDest, XDM1_SingleBufDesc *pSrc, XDAS_Int32 numBufs, XDAS_Int32 maxBufs) { int i, foundBufs; for (i = 0, foundBufs = 0; ((foundBufs < numBufs) && (i < maxBufs)); i++) { if (pSrc[i].buf != NULL) { /* valid member of sparse array, convert it */ pDest[i].bufSize =pSrc[i].bufSize; pDest[i].buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(pSrc[i].buf, pSrc[i].bufSize, NULL); if (pDest[i].buf == NULL) { foundBufs = -1; break; } /* Clear .accessMask; the local processor won't access this buf */ pDest[i].accessMask = 0; /* found, and handled, another buffer. */ foundBufs++; } else { /* empty member of sparse array, no conversion needed. */ pDest[i].bufSize = 0; pDest[i].buf = NULL; } } return (foundBufs); }
/****************************************************************************** * Buffer_create ******************************************************************************/ Buffer_Handle Buffer_create(Int32 size, Buffer_Attrs *attrs) { Buffer_Handle hBuf; UInt32 objSize; if (attrs == NULL) { Dmai_err0("Must provide attrs\n"); return NULL; } if (attrs->type != Buffer_Type_BASIC && attrs->type != Buffer_Type_GRAPHICS) { Dmai_err1("Unknown Buffer type (%d)\n", attrs->type); return NULL; } objSize = attrs->type == Buffer_Type_GRAPHICS ? sizeof(_BufferGfx_Object) : sizeof(_Buffer_Object); hBuf = (Buffer_Handle) calloc(1, objSize); if (hBuf == NULL) { Dmai_err0("Failed to allocate space for Buffer Object\n"); return NULL; } _Buffer_init(hBuf, size, attrs); if (!attrs->reference) { hBuf->userPtr = (Int8*)Memory_alloc(size, &attrs->memParams); if (hBuf->userPtr == NULL) { printf("Failed to allocate memory.\n"); free(hBuf); return NULL; } hBuf->physPtr = Memory_getBufferPhysicalAddress(hBuf->userPtr, size, NULL); Dmai_dbg3("Alloc Buffer of size %u at 0x%x (0x%x phys)\n", (Uns) size, (Uns) hBuf->userPtr, (Uns) hBuf->physPtr); } hBuf->reference = attrs->reference; return hBuf; }
/* * ======== ceapp_allocContigBuf ======== */ char *ceapp_allocContigBuf(int bufSize, char *description) { char *buf; printf("CEapp-> Allocating contiguous buffer for '%s' of size %d...\n", description, bufSize); buf = (char *)Memory_contigAlloc(bufSize, Memory_DEFAULTALIGNMENT); if (buf == NULL) { printf("CEapp-> ERROR: Failed to allocate contiguous memory block.\n"); } else { printf("CEapp-> Contiguous buffer allocated OK (phys. addr=0x%x)\n", (int)Memory_getBufferPhysicalAddress(buf, bufSize, NULL)); } return buf; }
/****************************************************************************** * Buffer_setUserPtr ******************************************************************************/ Int Buffer_setUserPtr(Buffer_Handle hBuf, Int8 *ptr) { assert(hBuf); if (!hBuf->reference) { return Dmai_EINVAL; } hBuf->userPtr = ptr; if (ptr) { hBuf->physPtr = Memory_getBufferPhysicalAddress(hBuf->userPtr, 4, NULL); } else { hBuf->physPtr = 0; } Dmai_dbg2("Set user pointer 0x%x (physical 0x%x)\n", (Uns) hBuf->userPtr, (Uns) hBuf->physPtr); return Dmai_EOK; }
static int copySingleBufDescArrayWithV2P(XDM1_SingleBufDesc *pDest, XDM1_SingleBufDesc *pSrc, XDAS_Int32 maxBufs) { int i; for (i = 0; (i < maxBufs) && (pSrc[i].buf != NULL); i++) { /* found another, convert it */ pDest[i].bufSize = pSrc[i].bufSize; pDest[i].buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(pSrc[i].buf, pSrc[i].bufSize, NULL); if (pDest[i].buf == NULL) { i = -1; break; } /* Clear .accessMask; the local processor won't access this buf */ pDest[i].accessMask = 0; } return (i); }
/* * ======== marshallMsg ======== */ static XDAS_Int32 marshallMsg(IAUDDEC_Handle h, XDM_BufDesc *inBufs, XDM_BufDesc *outBufs, IAUDDEC_InArgs *inArgs, IAUDDEC_OutArgs *outArgs, _AUDDEC_Msg **pmsg) { XDAS_Int32 retVal = IAUDDEC_EOK; VISA_Handle visa = (VISA_Handle)h; _AUDDEC_Msg *msg; Int i; IAUDDEC_OutArgs *pMsgOutArgs; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((inArgs == NULL) || (inArgs->size < sizeof(IAUDDEC_InArgs)) || (outArgs == NULL) || (outArgs->size < sizeof(IAUDDEC_OutArgs))) { /* invalid args, could even assert here, it's a spec violation. */ return (AUDDEC_EFAIL); } /* * Initialize extendedError to zero so we don't return something * uninitialized in extendedError. */ outArgs->extendedError = 0; if (pmsg == NULL) { return (AUDDEC_EFAIL); } /* make sure it'll all fit! */ payloadSize = sizeof(VISA_MsgHeader) + (sizeof(msg->cmd.process.inBufs) * XDM_MAX_IO_BUFFERS) + sizeof(msg->cmd.process.numInBufs) + (sizeof(msg->cmd.process.inBufSizes[0]) * XDM_MAX_IO_BUFFERS) + (sizeof(msg->cmd.process.outBufs) * XDM_MAX_IO_BUFFERS) + sizeof(msg->cmd.process.numOutBufs) + (sizeof(msg->cmd.process.outBufSizes[0]) * XDM_MAX_IO_BUFFERS) + inArgs->size + outArgs->size; if (payloadSize > VISA_getMaxMsgSize(visa)) { /* Can't handle these large extended args. */ Log_print2(Diags_USER6, "[+6] process> invalid arguments - too big (0x%x > 0x%x). " "Validate .size fields", payloadSize, VISA_getMaxMsgSize(visa)); return (IAUDDEC_EFAIL); } /* get a message appropriate for this algorithm */ if ((msg = (_AUDDEC_Msg *)VISA_allocMsg(visa)) == NULL) { return (IAUDDEC_ERUNTIME); } /* * Marshall the command: copy the client-passed arguments into flattened * message data structures, converting every pointer address to alg. * data buffer into physical address. */ /* First specify the processing command that the skeleton should do */ msg->visa.cmd = _AUDDEC_CPROCESS; /* commentary follows for marshalling the inBufs argument: */ /* 1) inBufs->numBufs is a plain integer, we just copy it */ msg->cmd.process.numInBufs = inBufs->numBufs; /* 2) inBufs->bufSizes is an array of integers, we copy them all */ for (i = 0; i < inBufs->numBufs; i++) { msg->cmd.process.inBufSizes[i] = inBufs->bufSizes[i]; } /* 3) inBufs->bufs is a pointer to an array of pointers, so we take * individual pointers, convert them, and store in the the message * counterpart of inBufs->bufs */ for (i = 0; i < inBufs->numBufs; i++) { msg->cmd.process.inBufs[i] = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(inBufs->bufs[i], inBufs->bufSizes[i], NULL); if (msg->cmd.process.inBufs[i] == NULL) { retVal = AUDDEC_ERUNTIME; goto exit; } } /* we're done (with inBufs). Because msg->cmd.process is non-cacheable * and contiguous (it has been allocated by MSGQ), we don't have to do * anything else. */ /* Now we repeat the procedure for outBufs. Note that * inArgs and outArgs contain no pointers, so we can simply copy the * entire original structure, accounting for the first "size" field. */ msg->cmd.process.numOutBufs = outBufs->numBufs; for (i = 0; i < outBufs->numBufs; i++) { msg->cmd.process.outBufSizes[i] = outBufs->bufSizes[i]; } for (i = 0; i < outBufs->numBufs; i++) { msg->cmd.process.outBufs[i] = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(outBufs->bufs[i], outBufs->bufSizes[i], NULL); if (msg->cmd.process.outBufs[i] == NULL) { retVal = AUDDEC_ERUNTIME; goto exit; } } /* inArgs has no pointers so simply memcpy "size" bytes into the msg */ memcpy(&(msg->cmd.process.inArgs), inArgs, inArgs->size); /* point at outArgs and set the "size" */ pMsgOutArgs = (IAUDDEC_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) + inArgs->size); /* set the size field - the rest is filled in by the codec */ /* TODO:H probably want to zero out the rest of the outArgs struct */ pMsgOutArgs->size = outArgs->size; *pmsg = msg; return (retVal); exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* Default implementation for _chain */ static GstFlowReturn gst_tidmai_base_video_dualencoder_default_realize_instance (GstTIDmaiBaseVideoDualEncoder *video_dualencoder, GstTIDmaiDualEncInstance *encoder_instance, GstBuffer *entry_buffer) { GST_DEBUG_OBJECT (video_dualencoder, "Entry gst_tidmai_base_video_dualencoder_default_realize_instance"); /* Only for test */ //GstClockTime time_start, time_start2, time_end, time_end2; //GstClockTimeDiff time_diff; Buffer_Attrs Attrs; Buffer_Handle outBufHandle; //Buffer_Attrs inAttrs; //Buffer_Handle inBufHandle; GstTIDmaiVideoInfo *video_info; UInt32 phys = 10; Bool isContiguous = FALSE; //time_start = gst_util_get_timestamp (); int ret; GstBuffer *buffer_push_out; /* Tests if the buffer */ phys = Memory_getBufferPhysicalAddress( GST_BUFFER_DATA(entry_buffer), GST_BUFFER_SIZE(entry_buffer), &isContiguous); if(phys == 0) { GST_ERROR_OBJECT (video_dualencoder, "Entry buffer isn't CMEM"); return GST_FLOW_NOT_SUPPORTED; } else { GST_DEBUG_OBJECT (video_dualencoder, "Using buffers with contiguos memory"); encoder_instance->input_buffer = entry_buffer; } /* Check for the output_buffer */ if (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->submitted_output_buffers == NULL) { video_info = (GstTIDmaiVideoInfo *) GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->high_resolution_encoder->media_info; GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->inBufSize = (video_info->width * video_info->height) * 1.8; if (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize == 0) { /* Default value for the out buffer size */ GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize = GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->inBufSize * 5; } /* Add the free memory slice to the list */ struct cmemSlice *slice = g_malloc0 (sizeof (struct cmemSlice)); slice->start = 0; slice->end = GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize; slice->size = GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize; #ifdef GLIB_2_31_AND_UP g_mutex_init(&(GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeMutex)); #else GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeMutex = g_mutex_new(); #endif GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeSlices = g_list_append (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeSlices, slice); /* Allocate the circular buffer */ Attrs = Buffer_Attrs_DEFAULT; Attrs.useMask = gst_tidmaibuffertransport_GST_FREE; outBufHandle = Buffer_create(GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize, &Attrs); GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->submitted_output_buffers = gst_tidmaibuffertransport_new(outBufHandle, NULL, NULL, FALSE); } /* Encode the actual buffer */ buffer_push_out = gst_tidmai_base_dualencoder_encode (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder), encoder_instance); gst_buffer_copy_metadata(buffer_push_out, entry_buffer, GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); //time_end = gst_util_get_timestamp (); //time_diff = GST_CLOCK_DIFF (time_start, time_end); //g_print ("DualEncoder time: %" G_GUINT64_FORMAT " ns.\n", time_diff); /* push the buffer and check for any error */ //time_start2 = gst_util_get_timestamp (); GST_BUFFER_CAPS (buffer_push_out) = gst_caps_ref(GST_PAD_CAPS(encoder_instance->src_pad)); ret = gst_pad_push (encoder_instance->src_pad, buffer_push_out); //time_end2 = gst_util_get_timestamp (); //time_diff = GST_CLOCK_DIFF (time_start2, time_end2); //g_print ("\nPush time: %" G_GUINT64_FORMAT " ns.\n\n", time_diff); if (GST_FLOW_OK != ret) { GST_ERROR_OBJECT (video_dualencoder, "Push buffer return with error: %d", ret); } GST_DEBUG_OBJECT (video_dualencoder, "Leave gst_tidmai_base_video_dualencoder_default_realize_instance"); return ret; }
/* * ======== marshallMsg ======== */ static XDAS_Int32 marshallMsg(IVIDDEC2_Handle h, XDM1_BufDesc *inBufs, XDM_BufDesc *outBufs, IVIDDEC2_InArgs *inArgs, IVIDDEC2_OutArgs *outArgs, _VIDDEC2_Msg **pmsg) { XDAS_Int32 retVal = IVIDDEC2_EOK; VISA_Handle visa = (VISA_Handle)h; _VIDDEC2_Msg *msg; Int i; IVIDDEC2_OutArgs *pMsgOutArgs; Int numBufs; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((inArgs == NULL) || (inArgs->size < sizeof(IVIDDEC2_InArgs)) || (outArgs == NULL) || (outArgs->size < sizeof(IVIDDEC2_OutArgs))) { /* invalid args, could even assert here, it's a spec violation. */ return (IVIDDEC2_EFAIL); } if (pmsg == NULL) { return (IVIDDEC2_EFAIL); } /* make sure it'll all fit! */ payloadSize = sizeof(VISA_MsgHeader) + (sizeof(*inBufs)) + (sizeof(outBufs[0]) * XDM_MAX_IO_BUFFERS) + sizeof(msg->cmd.process.numOutBufs) + (sizeof(msg->cmd.process.outBufSizes[0]) * XDM_MAX_IO_BUFFERS) + inArgs->size + outArgs->size; if (payloadSize > VISA_getMaxMsgSize(visa)) { /* Can't handle these large extended args. */ Log_print2(Diags_USER6, "[+6] process> invalid arguments - too big (0x%x > 0x%x). " "Validate .size fields", payloadSize, VISA_getMaxMsgSize(visa)); return (IVIDDEC2_EUNSUPPORTED); } /* get a message appropriate for this algorithm */ if ((msg = (_VIDDEC2_Msg *)VISA_allocMsg(visa)) == NULL) { return (IVIDDEC2_EFAIL); } /* zero out msg->cmd (not msg->visa!) */ memset(&(msg->cmd), 0, sizeof(msg->cmd)); /* * Marshall the command: copy the client-passed arguments into flattened * message data structures, converting every pointer address to alg. * data buffer into physical address. */ /* First specify the processing command that the skeleton should do */ msg->visa.cmd = _VIDDEC2_CPROCESS; /* commentary follows for marshalling the inBufs argument: */ /* 1) inBufs->numBufs is a plain integer, we just copy it */ msg->cmd.process.inBufs.numBufs = inBufs->numBufs; /* * 2) inBufs->bufSizes is a sparse array of integers, we copy them all. * * 3) inBufs->bufs is a pointer to a sparse array of pointers, so we take * individual pointers, convert them if non-NULL, and store them in the * message counterpart of inBufs->bufs. */ for (i = 0, numBufs = 0; ((numBufs < inBufs->numBufs) && (i < XDM_MAX_IO_BUFFERS)); i++) { if (inBufs->descs[i].buf != NULL) { /* valid member of sparse array, convert it */ msg->cmd.process.inBufs.descs[i].bufSize = inBufs->descs[i].bufSize; msg->cmd.process.inBufs.descs[i].buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(inBufs->descs[i].buf, inBufs->descs[i].bufSize, NULL); if (msg->cmd.process.inBufs.descs[i].buf == NULL) { retVal = IVIDDEC2_EFAIL; goto exit; } /* Clear .accessMask; the local processor won't access this buf */ inBufs->descs[i].accessMask = 0; /* found, and handled, another buffer. */ numBufs++; } else { /* empty member of sparse array, no conversion needed. */ msg->cmd.process.inBufs.descs[i].bufSize = 0; msg->cmd.process.inBufs.descs[i].buf = NULL; } } if (VISA_isChecked()) { /* check that we found inBufs->numBufs pointers in inBufs->bufs[] */ Assert_isTrue(inBufs->numBufs == numBufs, (Assert_Id)NULL); } /* we're done (with inBufs). Because msg->cmd.process is non-cacheable * and contiguous (it has been allocated by MSGQ), we don't have to do * anything else. */ /* Now we repeat the procedure for outBufs. Note that * inArgs contains no pointers, so we can simply copy the * entire original structure, accounting for the first "size" field. */ msg->cmd.process.numOutBufs = outBufs->numBufs; for (i = 0, numBufs = 0; ((numBufs < outBufs->numBufs) && (i < XDM_MAX_IO_BUFFERS)); i++) { if (outBufs->bufs[i] != NULL) { /* valid member of sparse array, convert it */ msg->cmd.process.outBufSizes[i] = outBufs->bufSizes[i]; msg->cmd.process.outBufs[i] = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(outBufs->bufs[i], outBufs->bufSizes[i], NULL); if (msg->cmd.process.outBufs[i] == NULL) { /* TODO:M - should add at least a trace statement when trace * is supported. Another good idea is to return something * more clear than EFAIL. */ retVal = IVIDDEC2_EFAIL; goto exit; } /* found, and handled, another buffer. */ numBufs++; } else { /* empty member of sparse array, no conversion needed */ msg->cmd.process.outBufSizes[i] = 0; msg->cmd.process.outBufs[i] = NULL; } } if (VISA_isChecked()) { /* check that we found outBufs->numBufs pointers in outBufs->bufs[] */ Assert_isTrue(outBufs->numBufs == numBufs, (Assert_Id)NULL); } /* inArgs has no pointers so simply memcpy "size" bytes into the msg */ memcpy(&(msg->cmd.process.inArgs), inArgs, inArgs->size); /* point at outArgs and set the "size" */ pMsgOutArgs = (IVIDDEC2_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) + inArgs->size); /* set the size field - the rest is filled in by the codec */ pMsgOutArgs->size = outArgs->size; *pmsg = msg; return (retVal); exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* * ======== control ======== * This is the stub-implementation for the control method */ static XDAS_Int32 control(IVIDDEC2_Handle h, IVIDDEC2_Cmd id, IVIDDEC2_DynamicParams *params, IVIDDEC2_Status *status) { XDAS_Int32 retVal; VISA_Handle visa = (VISA_Handle)h; _VIDDEC2_Msg *msg; IVIDDEC2_Status *pMsgStatus; XDAS_Int8 *virtAddr = NULL; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((params == NULL) || (params->size < sizeof(IVIDDEC2_DynamicParams)) || (status == NULL) || (status->size < sizeof(IVIDDEC2_Status))) { /* invalid args, could even assert here, it's a spec violation. */ return (IVIDDEC2_EFAIL); } /* * Initialize extendedError to zero so we don't return something * uninitialized in extendedError. */ status->extendedError = 0; /* make sure it'll all fit! */ payloadSize = sizeof(VISA_MsgHeader) + sizeof(id) + params->size + status->size; if (payloadSize > VISA_getMaxMsgSize(visa)) { /* Can't handle these large extended args. */ Log_print2(Diags_USER6, "[+6] control> invalid arguments - too big (0x%x > 0x%x). " "Validate .size fields", payloadSize, VISA_getMaxMsgSize(visa)); return (IVIDDEC2_EUNSUPPORTED); } /* get a message appropriate for this algorithm */ if ((msg = (_VIDDEC2_Msg *)VISA_allocMsg(visa)) == NULL) { return (IVIDDEC2_EFAIL); } /* marshall the command */ msg->visa.cmd = _VIDDEC2_CCONTROL; msg->cmd.control.id = id; /* params has no pointers so simply memcpy "size" bytes into the msg */ memcpy(&(msg->cmd.control.params), params, params->size); /* unmarshall status based on the "size" of params */ pMsgStatus = (IVIDDEC2_Status *)((UInt)(&(msg->cmd.control.params)) + params->size); /* * Initialize the .size and .data fields - the rest are filled in by * the codec. */ pMsgStatus->size = status->size; if (status->data.buf != NULL) { pMsgStatus->data.bufSize = status->data.bufSize; /* save it for later */ virtAddr = status->data.buf; pMsgStatus->data.buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(status->data.buf, status->data.bufSize, NULL); if (pMsgStatus->data.buf == NULL) { retVal = IVIDDEC2_EFAIL; goto exit; } } else { /* Place null into the msg so the skel knows it's invalid */ pMsgStatus->data.buf = NULL; } /* send the message to the skeleton and wait for completion */ retVal = VISA_call(visa, (VISA_Msg *)&msg); /* ensure we get CCONTROL msg (ensure async CPROCESS pipeline drained) */ Assert_isTrue(msg->visa.cmd == _VIDDEC2_CCONTROL, (Assert_Id)NULL); /* unmarshall status */ pMsgStatus = (IVIDDEC2_Status *)((UInt)(&(msg->cmd.control.params)) + params->size); if (VISA_isChecked()) { /* ensure codec didn't modify status->size */ Assert_isTrue(pMsgStatus->size == status->size, (Assert_Id)NULL); /* * TODO:L Should we also check that pMsgStatus->data.buf is the same * after the call as before? */ } memcpy(status, pMsgStatus, status->size); /* * And finally, restore status->data.buf to its original value. Note that * this works even when status->data.buf was NULL because virtAddr is * initialized to NULL. * * While potentially more confusing, this is just as correct as * (and faster than!) calling Memory_getVirtualBuffer(). */ status->data.buf = virtAddr; /* Clear .accessMask; the local processor didn't access the buffer */ status->data.accessMask = 0; exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* * ======== control ======== * This is the stub-implementation for the control method */ static XDAS_Int32 control(IVIDDEC2BACK_Handle h, XDM_Context *context, IVIDDEC2_Status *status) { XDAS_Int32 retVal; VISA_Handle visa = (VISA_Handle)h; _VIDDEC2BACK_Msg *msg; // IVIDDEC2_Status *pMsgStatus; // XDAS_Int8 *virtAddr = NULL; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((context == NULL) || (status == NULL) || (status->size < sizeof(IVIDDEC2_Status))) { /* invalid args, could even assert here, it's a spec violation. */ return (IVIDDEC2_EFAIL); } if (/* size of "stuff to marshall" > message size */ (sizeof(VISA_MsgHeader) + sizeof(*context) + status->size) > sizeof(_VIDDEC2BACK_Msg)) { /* Can't handle these large extended args. */ Log_print0(Diags_USER6, "[+6] control> invalid arguments - validate .size fields"); return (IVIDDEC2_EUNSUPPORTED); } /* get a message appropriate for this algorithm */ if ((msg = (_VIDDEC2BACK_Msg *)VISA_allocMsg(visa)) == NULL) { return (IVIDDEC2_EFAIL); } /* marshall the command */ msg->visa.cmd = _VIDDEC2BACK_CCONTROL; /* * Initialize the .size and .data fields - the rest are filled in by * the codec. */ msg->cmd.control.status.size = status->size; #if 0 if (status->data.buf != NULL) { pMsgStatus->data.bufSize = status->data.bufSize; /* save it for later */ virtAddr = status->data.buf; pMsgStatus->data.buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(status->data.buf, status->data.bufSize, NULL); if (pMsgStatus->data.buf == NULL) { retVal = IVIDDEC2_EFAIL; goto exit; } } else { /* Place null into the msg so the skel knows it's invalid */ pMsgStatus->data.buf = NULL; } #endif /* send the message to the skeleton and wait for completion */ retVal = VISA_call(visa, (VISA_Msg *)&msg); /* ensure we get CCONTROL msg (ensure async CPROCESS pipeline drained) */ Assert_isTrue(msg->visa.cmd == _VIDDEC2BACK_CCONTROL, (Assert_Id)NULL); if (VISA_isChecked()) { /* ensure codec didn't modify status->size */ Assert_isTrue(msg->cmd.control.status.size == status->size, (Assert_Id)NULL); /* * TODO:L Should we also check that pMsgStatus->data.buf is the same * after the call as before? */ } memcpy(status, &(msg->cmd.control.status), status->size); #if 0 /* * And finally, restore status->data.buf to its original value. Note that * this works even when status->data.buf was NULL because virtAddr is * initialized to NULL. * * While potentially more confusing, this is just as correct as * (and faster than!) calling Memory_getVirtualBuffer(). */ status->data.buf = virtAddr; /* Clear .accessMask; the local processor didn't access the buffer */ status->data.accessMask = 0; #endif //exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* * ======== marshallMsg ======== */ static XDAS_Int32 marshallMsg(IVIDDEC2BACK_Handle h, XDM_Context *context, IVIDDEC2_OutArgs *outArgs, _VIDDEC2BACK_Msg **pmsg) { XDAS_Int32 retVal = IVIDDEC2_EOK; VISA_Handle visa = (VISA_Handle)h; _VIDDEC2BACK_Msg *msg; Int numBufs; Assert_isTrue(pmsg != NULL, (Assert_Id)NULL); /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((context == NULL) || (outArgs == NULL) || (outArgs->size < sizeof(IVIDDEC2_OutArgs))) { /* invalid args, could even assert here, it's a spec violation. */ return (IVIDDEC2_EFAIL); } if (/* size of "stuff to marshall" > message size */ (sizeof(VISA_MsgHeader) + sizeof(XDM_Context) + outArgs->size) > sizeof(_VIDDEC2BACK_Msg)) { /* Can't handle these large extended args. */ Log_print0(Diags_USER6, "[+6] process> invalid arguments - outArgs.size field is too" " large"); return (IVIDDEC2_EUNSUPPORTED); } /* get a message appropriate for this algorithm */ if ((msg = (_VIDDEC2BACK_Msg *)VISA_allocMsg(visa)) == NULL) { Log_print0(Diags_USER6, "[+6] process> VISA_allocMsg failed"); return (IVIDDEC2_EFAIL); } /* zero out msg->cmd (not msg->visa!) */ memset(&(msg->cmd), 0, sizeof(msg->cmd)); /* * Marshall the command: copy the client-passed arguments into flattened * message data structures, converting every pointer address to alg. * data buffer into physical address. */ /* First specify the processing command that the skeleton should do */ msg->visa.cmd = _VIDDEC2BACK_CPROCESS; /* address translation of XDM_Context buffers */ if (context->algContext.buf != NULL) { msg->cmd.process.context.algContext.bufSize = context->algContext.bufSize; msg->cmd.process.context.algContext.buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(context->algContext.buf, context->algContext.bufSize, NULL); if (msg->cmd.process.context.algContext.buf == NULL) { retVal = IVIDDEC2_EFAIL; goto exit; } } /* context->num*Bufs are plain integers, just copy them */ msg->cmd.process.context.numInBufs = context->numInBufs; msg->cmd.process.context.numOutBufs = context->numOutBufs; msg->cmd.process.context.numInOutBufs = context->numInOutBufs; /* address translate inBufs */ numBufs = copySparseSingleBufDescArrayWithV2P(msg->cmd.process.context.inBufs, context->inBufs, context->numInBufs, XDM_MAX_CONTEXT_BUFFERS); if (numBufs == -1) { retVal = IVIDDEC2_EFAIL; goto exit; } if (VISA_isChecked()) { /* check that we found context->numInBufs in context->inBufs */ Assert_isTrue(context->numInBufs == numBufs, (Assert_Id)NULL); } /* Repeat the procedure for outBufs and intermediateBufs. */ numBufs = copySparseSingleBufDescArrayWithV2P(msg->cmd.process.context.outBufs, context->outBufs, context->numOutBufs, XDM_MAX_CONTEXT_BUFFERS); if (numBufs == -1) { retVal = IVIDDEC2_EFAIL; goto exit; } if (VISA_isChecked()) { /* check that we found context->numOutBufs in context->outBufs */ Assert_isTrue(context->numOutBufs == numBufs, (Assert_Id)NULL); } numBufs = copySingleBufDescArrayWithV2P(msg->cmd.process.context.intermediateBufs, context->intermediateBufs, XDM_MAX_CONTEXT_BUFFERS); if (numBufs == -1) { retVal = IVIDDEC2_EFAIL; goto exit; } /* VIDDEC2BACK doesn't support any in/out buffers */ if (VISA_isChecked()) { Assert_isTrue(context->numInOutBufs == 0, (Assert_Id)NULL); } /* outArgs has no 'inputs', so only .size needs marshalled */ msg->cmd.process.outArgs.size = outArgs->size; *pmsg = msg; return (retVal); exit: VISA_freeMsg(visa, (VISA_Msg)msg); return retVal; }
int cont_alloc_frames(struct frame_format *ff, unsigned bufsize, struct frame **fr, unsigned *nf) { int buf_w = ff->width, buf_h = ff->height; uint8_t *p = NULL; uint8_t *pp = NULL; unsigned y_offset; int i, clear_count; mem_params.type = Memory_CONTIGHEAP; mem_params.flags = Memory_NONCACHED; mem_params.align = 16; input_buf = Memory_alloc(INPUT_BUFFER_SIZE, &mem_params); if (!input_buf) { fprintf(stderr, "Error allocating input buffer\n"); return -1; } ce_frame_size = buf_w * buf_h * 2; num_frames = bufsize / ce_frame_size; y_offset = buf_w * buf_h; fprintf(stderr, "MAIN CE Memory Manager: using %d CMEM HEAP allocated frame buffers, with size: %u\n", num_frames, ce_frame_size); frames = malloc(num_frames * sizeof(*frames)); for (i = 0; i < num_frames; i++) { p = Memory_alloc(ce_frame_size, &mem_params); if (!p) { fprintf(stderr, "Error allocating frame buffer %d on CMEM\n", i); goto err; } pp = (uint8_t *)Memory_getBufferPhysicalAddress(p, ce_frame_size, NULL); frames[i].virt[0] = p; frames[i].virt[1] = p + y_offset; frames[i].virt[2] = p + y_offset + buf_w / 2; frames[i].phys[0] = pp; frames[i].phys[1] = pp + y_offset; frames[i].phys[2] = pp + y_offset + buf_w / 2; frames[i].linesize[0] = ff->width; frames[i].linesize[1] = ff->width; frames[i].linesize[2] = ff->width; } ff->y_stride = ff->width; ff->uv_stride = ff->width; *fr = frames; *nf = num_frames; return 0; err: clear_count = i; for (i=0; i<clear_count; i++) { if (!frames) break; Memory_free(frames[i].virt[0], ce_frame_size, &mem_params); } Memory_free(input_buf, INPUT_BUFFER_SIZE, &mem_params); if (frames) free(frames); return -1; }
/***************************************************************************** * gst_tidmaiaccel_prepare_output_buffer * Function is used to allocate output buffer *****************************************************************************/ static GstFlowReturn gst_tidmaiaccel_prepare_output_buffer (GstBaseTransform *trans, GstBuffer *inBuf, gint size, GstCaps *caps, GstBuffer **outBuf) { GstTIDmaiaccel *dmaiaccel = GST_TIDMAIACCEL(trans); Buffer_Handle hOutBuf; Bool isContiguous = FALSE; UInt32 phys = 0; /* Always check if the buffer is contiguous */ phys = Memory_getBufferPhysicalAddress( GST_BUFFER_DATA(inBuf), GST_BUFFER_SIZE(inBuf), &isContiguous); if (isContiguous && dmaiaccel->width){ GST_DEBUG("Is contiguous video buffer"); Memory_registerContigBuf((UInt32)GST_BUFFER_DATA(inBuf), GST_BUFFER_SIZE(inBuf),phys); /* This is a contiguous buffer, create a dmai buffer transport */ BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; gfxAttrs.bAttrs.reference = TRUE; gfxAttrs.dim.width = dmaiaccel->width; gfxAttrs.dim.height = dmaiaccel->height; gfxAttrs.colorSpace = dmaiaccel->colorSpace; gfxAttrs.dim.lineLength = dmaiaccel->lineLength; hOutBuf = Buffer_create(GST_BUFFER_SIZE(inBuf), &gfxAttrs.bAttrs); BufferGfx_setDimensions(hOutBuf,&gfxAttrs.dim); BufferGfx_setColorSpace(hOutBuf,gfxAttrs.colorSpace); Buffer_setUserPtr(hOutBuf, (Int8*)GST_BUFFER_DATA(inBuf)); Buffer_setNumBytesUsed(hOutBuf, GST_BUFFER_SIZE(inBuf)); *outBuf = gst_tidmaibuffertransport_new(hOutBuf, NULL, NULL, FALSE); gst_buffer_set_data(*outBuf, (guint8*) Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); gst_buffer_copy_metadata(*outBuf,inBuf,GST_BUFFER_COPY_ALL); gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad)); /* We need to grab a reference to the input buffer since we have * a pointer to his buffer */ gst_buffer_ref(inBuf); gst_tidmaibuffertransport_set_release_callback( (GstTIDmaiBufferTransport *)*outBuf, dmaiaccel_release_cb,inBuf); return GST_FLOW_OK; } else { GST_DEBUG("Copying into contiguous video buffer"); /* This is a contiguous buffer, create a dmai buffer transport */ if (!dmaiaccel->bufTabAllocated){ /* Initialize our buffer tab */ BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; gfxAttrs.dim.width = dmaiaccel->width; gfxAttrs.dim.height = dmaiaccel->height; gfxAttrs.colorSpace = dmaiaccel->colorSpace; gfxAttrs.dim.lineLength = dmaiaccel->lineLength; dmaiaccel->hOutBufTab = BufTab_create(2, GST_BUFFER_SIZE(inBuf), BufferGfx_getBufferAttrs(&gfxAttrs)); pthread_mutex_init(&dmaiaccel->bufTabMutex, NULL); pthread_cond_init(&dmaiaccel->bufTabCond, NULL); if (dmaiaccel->hOutBufTab == NULL) { GST_ELEMENT_ERROR(dmaiaccel,RESOURCE,NO_SPACE_LEFT,(NULL), ("failed to create output buffer tab")); return GST_FLOW_ERROR; } dmaiaccel->bufTabAllocated = TRUE; } pthread_mutex_lock(&dmaiaccel->bufTabMutex); hOutBuf = BufTab_getFreeBuf(dmaiaccel->hOutBufTab); if (hOutBuf == NULL) { GST_INFO("Failed to get free buffer, waiting on bufTab\n"); pthread_cond_wait(&dmaiaccel->bufTabCond, &dmaiaccel->bufTabMutex); hOutBuf = BufTab_getFreeBuf(dmaiaccel->hOutBufTab); if (hOutBuf == NULL) { GST_ELEMENT_ERROR(dmaiaccel,RESOURCE,NO_SPACE_LEFT,(NULL), ("failed to get a free contiguous buffer from BufTab")); pthread_mutex_unlock(&dmaiaccel->bufTabMutex); return GST_FLOW_ERROR; } } pthread_mutex_unlock(&dmaiaccel->bufTabMutex); memcpy(Buffer_getUserPtr(hOutBuf),GST_BUFFER_DATA(inBuf), GST_BUFFER_SIZE(inBuf)); Buffer_setNumBytesUsed(hOutBuf, GST_BUFFER_SIZE(inBuf)); *outBuf = gst_tidmaibuffertransport_new(hOutBuf, &dmaiaccel->bufTabMutex, &dmaiaccel->bufTabCond, FALSE); gst_buffer_set_data(*outBuf, (guint8*) Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); gst_buffer_copy_metadata(*outBuf,inBuf,GST_BUFFER_COPY_ALL); gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad)); return GST_FLOW_OK; } }
/* * ======== marshallMsg ======== */ static XDAS_Int32 marshallMsg(IVIDENC1_Handle h, IVIDEO1_BufDescIn *inBufs, XDM_BufDesc *outBufs, IVIDENC1_InArgs *inArgs, IVIDENC1_OutArgs *outArgs, _VIDENC1_Msg **pmsg) { XDAS_Int32 retVal = IVIDENC1_EOK; VISA_Handle visa = (VISA_Handle)h; _VIDENC1_Msg *msg; Int i; IVIDENC1_OutArgs *pMsgOutArgs; Int numBufs; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((inArgs == NULL) || (inArgs->size < sizeof(IVIDENC1_InArgs)) || (outArgs == NULL) || (outArgs->size < sizeof(IVIDENC1_OutArgs))) { /* invalid args, could even assert here, it's a spec violation. */ return (IVIDENC1_EFAIL); } /* * Initialize extendedError to zero so we don't return something * uninitialized in extendedError. */ outArgs->extendedError = 0; if (pmsg == NULL) { return (IVIDENC1_EFAIL); } /* make sure it'll all fit! */ payloadSize = sizeof(VISA_MsgHeader) + sizeof(*inBufs) + (sizeof(msg->cmd.process.outBufs) * XDM_MAX_IO_BUFFERS) + sizeof(msg->cmd.process.numOutBufs) + (sizeof(msg->cmd.process.outBufSizes[0]) * XDM_MAX_IO_BUFFERS) + inArgs->size + outArgs->size; if (payloadSize > VISA_getMaxMsgSize(visa)) { /* Can't handle these large extended args. */ Log_print2(Diags_USER6, "[+6] process> invalid arguments - too big (0x%x > 0x%x). " "Validate .size fields", payloadSize, VISA_getMaxMsgSize(visa)); return (IVIDENC1_EUNSUPPORTED); } /* get a message appropriate for this algorithm */ if ((msg = (_VIDENC1_Msg *)VISA_allocMsg(visa)) == NULL) { return (IVIDENC1_EFAIL); } /* zero out msg->cmd (not msg->visa!) */ memset(&(msg->cmd), 0, sizeof(msg->cmd)); /* * Marshall the command: copy the client-passed arguments into flattened * message data structures, converting every pointer address to alg. * data buffer into physical address. */ /* First specify the processing command that the skeleton should do */ msg->visa.cmd = _VIDENC1_CPROCESS; /* commentary follows for marshalling the inBufs argument: */ /* 1) copy integers */ msg->cmd.process.inBufs.numBufs = inBufs->numBufs; msg->cmd.process.inBufs.frameWidth = inBufs->frameWidth; msg->cmd.process.inBufs.frameHeight = inBufs->frameHeight; msg->cmd.process.inBufs.framePitch = inBufs->framePitch; /* * inBufs->bufDesc is a sparse array of buffer descriptors. Convert them * if non-NULL. */ for (i = 0, numBufs = 0; i < XDM_MAX_IO_BUFFERS; i++) { if (inBufs->bufDesc[i].buf != NULL) { /* valid member of sparse array, copy .bufSize convert .buf */ msg->cmd.process.inBufs.bufDesc[i].bufSize = inBufs->bufDesc[i].bufSize; msg->cmd.process.inBufs.bufDesc[i].buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(inBufs->bufDesc[i].buf, inBufs->bufDesc[i].bufSize, NULL); if (msg->cmd.process.inBufs.bufDesc[i].buf == NULL) { retVal = IVIDENC1_EFAIL; goto exit; } /* Clear .accessMask; the local processor won't access this buf */ inBufs->bufDesc[i].accessMask = 0; /* found, and handled, another buffer. See if it's the last one */ if (++numBufs == inBufs->numBufs) { break; } } else { /* empty member of sparse array, no conversion needed. */ msg->cmd.process.inBufs.bufDesc[i].bufSize = 0; msg->cmd.process.inBufs.bufDesc[i].buf = NULL; } } /* we're done (with inBufs). Because msg->cmd.process is non-cacheable * and contiguous (it has been allocated by MSGQ), we don't have to do * anything else. */ /* Repeat the procedure for outBufs. */ msg->cmd.process.numOutBufs = outBufs->numBufs; for (i = 0, numBufs = 0; i < XDM_MAX_IO_BUFFERS; i++) { if (outBufs->bufs[i] != NULL) { /* valid member of sparse array, convert it */ msg->cmd.process.outBufSizes[i] = outBufs->bufSizes[i]; msg->cmd.process.outBufs[i] = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(outBufs->bufs[i], outBufs->bufSizes[i], NULL); if (msg->cmd.process.outBufs[i] == NULL) { /* TODO:M - should add at least a trace statement when trace * is supported. Another good idea is to return something * more clear than EFAIL. */ retVal = IVIDENC1_EFAIL; goto exit; } /* found, and handled, another buffer. See if it's the last one */ if (++numBufs == outBufs->numBufs) { break; } } else { /* empty member of sparse array, no conversion needed */ msg->cmd.process.outBufSizes[i] = 0; msg->cmd.process.outBufs[i] = NULL; } } /* inArgs has no pointers so simply memcpy "size" bytes into the msg */ memcpy(&(msg->cmd.process.inArgs), inArgs, inArgs->size); /* point at outArgs and set the "size" */ pMsgOutArgs = (IVIDENC1_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) + inArgs->size); /* set the size field - the rest is filled in by the codec */ pMsgOutArgs->size = outArgs->size; /* * Note that although outArgs contains pointers, they're not provided * by the application via the outArgs struct. Rather the actual buffers * are provided by the application to the algorithm via outBufs. * So, the addresses in outArgs are output only, and do not require * address translation _before_ calling process(). They _do_ require * adress translation _after_ process(), as the algorithm may have written * physical addresses into the pointers. */ *pmsg = msg; return (retVal); exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* * ======== control ======== * This is the stub-implementation for the control method */ static XDAS_Int32 control(IUNIVERSAL_Handle h, IUNIVERSAL_Cmd id, IUNIVERSAL_DynamicParams *dynParams, IUNIVERSAL_Status *status) { XDAS_Int32 retVal; VISA_Handle visa = (VISA_Handle)h; _UNIVERSAL_Msg *msg; IUNIVERSAL_Status *pMsgStatus; XDAS_Int8 *virtAddr[XDM_MAX_IO_BUFFERS]; Int i; Int numBufs; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((dynParams == NULL) || (dynParams->size < sizeof(IUNIVERSAL_DynamicParams)) || (status == NULL) || (status->size < sizeof(IUNIVERSAL_Status))) { /* invalid args, could even assert here, it's a spec violation. */ return (IUNIVERSAL_EFAIL); } /* * Initialize extendedError to zero so we don't return something * uninitialized in extendedError. */ status->extendedError = 0; /* make sure it'll all fit! */ payloadSize = sizeof(VISA_MsgHeader) + sizeof(id) + dynParams->size + status->size; if (payloadSize > VISA_getMaxMsgSize(visa)) { /* Can't handle these large extended args. */ Log_print2(Diags_USER6, "[+6] control> invalid arguments - too big (0x%x > 0x%x). " "Validate .size fields", payloadSize, VISA_getMaxMsgSize(visa)); return (IUNIVERSAL_EUNSUPPORTED); } /* get a message appropriate for this algorithm */ if ((msg = (_UNIVERSAL_Msg *)VISA_allocMsg(visa)) == NULL) { return (IUNIVERSAL_EFAIL); } /* marshall the command */ msg->visa.cmd = _UNIVERSAL_CCONTROL; msg->cmd.control.id = id; /* dynParams has no pointers so simply memcpy "size" bytes into the msg */ memcpy(&(msg->cmd.control.dynParams), dynParams, dynParams->size); /* point at status based on the "size" of dynParams */ pMsgStatus = (IUNIVERSAL_Status *)((UInt)(&(msg->cmd.control.dynParams)) + dynParams->size); /* * Initialize the .size and .data fields - the rest are filled in by * the codec. */ pMsgStatus->size = status->size; /* 1) pMsgStatus->data.numBufs is a plain integer, we just copy it */ pMsgStatus->data.numBufs = status->data.numBufs; /* * status->data.descs[] is a sparse array of buffer descriptors. Convert * them if non-NULL. */ for (i = 0, numBufs = 0; ((numBufs < status->data.numBufs) && (i < XDM_MAX_IO_BUFFERS)); i++) { if (status->data.descs[i].buf != NULL) { /* valid member of sparse array, convert it */ pMsgStatus->data.descs[i].bufSize = status->data.descs[i].bufSize; /* save it for later */ virtAddr[i] = status->data.descs[i].buf; pMsgStatus->data.descs[i].buf = (XDAS_Int8 *) Memory_getBufferPhysicalAddress(status->data.descs[i].buf, status->data.descs[i].bufSize, NULL); if (pMsgStatus->data.descs[i].buf == NULL) { retVal = IUNIVERSAL_EFAIL; goto exit; } /* found, and handled, another buffer. */ numBufs++; } else { /* empty member of sparse array, no conversion needed. */ pMsgStatus->data.descs[i].bufSize = 0; pMsgStatus->data.descs[i].buf = NULL; virtAddr[i] = NULL; } } if (VISA_isChecked()) { /* check that we found inBufs->numBufs pointers in inBufs->bufs[] */ Assert_isTrue(status->data.numBufs == numBufs, (Assert_Id)NULL); } /* send the message to the skeleton and wait for completion */ retVal = VISA_call(visa, (VISA_Msg *)&msg); /* ensure we get CCONTROL msg (ensure async CPROCESS pipeline drained) */ Assert_isTrue(msg->visa.cmd == _UNIVERSAL_CCONTROL, (Assert_Id)NULL); /* unmarshall status */ pMsgStatus = (IUNIVERSAL_Status *)((UInt)(&(msg->cmd.control.dynParams)) + dynParams->size); if (VISA_isChecked()) { /* ensure codec didn't modify status->size */ Assert_isTrue(pMsgStatus->size == status->size, (Assert_Id)NULL); /* * TODO:L Should we also check that pMsgStatus->data.buf is the same * after the call as before? */ } memcpy(status, pMsgStatus, status->size); /* * And finally, restore status->data.descs[].buf's to their original values. * * While potentially more confusing, this is just as correct as * (and faster than!) calling Memory_getVirtualBuffer(). */ for (i = 0, numBufs = 0; (numBufs < status->data.numBufs) && (i < XDM_MAX_IO_BUFFERS); i++) { status->data.descs[i].buf = virtAddr[i]; /* Clear .accessMask; the local processor didn't access the buffer */ status->data.descs[i].accessMask = 0; if (virtAddr[i] != NULL) { numBufs++; } } exit: VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }