/* * ======== control ======== * This is the stub-implementation for the control method */ static XDAS_Int32 control(IAUDDEC_Handle h, IAUDDEC_Cmd id, IAUDDEC_DynamicParams *params, IAUDDEC_Status *status) { XDAS_Int32 retVal; VISA_Handle visa = (VISA_Handle)h; _AUDDEC_Msg *msg; IAUDDEC_Status *pMsgStatus; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((params == NULL) || (params->size < sizeof(IAUDDEC_DynamicParams)) || (status == NULL) || (status->size < sizeof(IAUDDEC_Status))) { /* invalid args, could even assert here, it's a spec violation. */ return (IAUDDEC_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] 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 */ msg->visa.cmd = _AUDDEC_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 = (IAUDDEC_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; /* 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 == _AUDDEC_CCONTROL, (Assert_Id)NULL); /* unmarshall status */ pMsgStatus = (IAUDDEC_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); } memcpy(status, pMsgStatus, status->size); VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* * ======== 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); }
/* * ======== control ======== * This is the stub-implementation for the control method */ static XDAS_Int32 control(ISPHDEC_Handle h, ISPHDEC_Cmd id, ISPHDEC_DynamicParams *params, ISPHDEC_Status *status) { XDAS_Int32 retVal; VISA_Handle visa = (VISA_Handle)h; _SPHDEC_Msg *msg; ISPHDEC_Status *pMsgStatus; Int payloadSize; /* * Validate arguments. Do we want to do this _every_ time, or just in * checked builds? */ if ((params == NULL) || (params->size < sizeof(ISPHDEC_DynamicParams)) || (status == NULL) || (status->size < sizeof(ISPHDEC_Status))) { /* invalid args, could even assert here, it's a spec violation. */ return (SPHDEC_EFAIL); } /* 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. */ GT_2trace(CURTRACE, GT_6CLASS, "process> invalid arguments - too big (0x%x > 0x%x). " "Validate .size fields\n", payloadSize, VISA_getMaxMsgSize(visa)); return (SPHDEC_EFAIL); } /* get a message appropriate for this algorithm */ if ((msg = (_SPHDEC_Msg *)VISA_allocMsg(visa)) == NULL) { return (ISPHDEC_ERUNTIME); } /* marshall the command */ msg->visa.cmd = _SPHDEC_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 = (ISPHDEC_Status *)((UInt)(&(msg->cmd.control.params)) + params->size); /* set the size field - the rest is filled in by the codec */ /* TODO:H probably want to zero out the rest of the status struct */ pMsgStatus->size = status->size; /* 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) */ GT_assert(CURTRACE, msg->visa.cmd == _SPHDEC_CCONTROL); /* unmarshall status */ pMsgStatus = (ISPHDEC_Status *)((UInt)(&(msg->cmd.control.params)) + params->size); if (VISA_isChecked()) { /* ensure codec didn't modify status->size */ GT_assert(CURTRACE, pMsgStatus->size == status->size); } memcpy(status, pMsgStatus, status->size); VISA_freeMsg(visa, (VISA_Msg)msg); return (retVal); }
/* * ======== 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); }
/* * ======== 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); }