diff options
Diffstat (limited to 'library/src')
-rw-r--r-- | library/src/mipi_syst_api.c | 1314 | ||||
-rw-r--r-- | library/src/mipi_syst_compiler.c | 78 | ||||
-rw-r--r-- | library/src/mipi_syst_crc32.c | 313 | ||||
-rw-r--r-- | library/src/mipi_syst_init.c | 204 | ||||
-rw-r--r-- | library/src/mipi_syst_inline.c | 48 | ||||
-rw-r--r-- | library/src/mipi_syst_writer.c | 219 |
6 files changed, 2176 insertions, 0 deletions
diff --git a/library/src/mipi_syst_api.c b/library/src/mipi_syst_api.c new file mode 100644 index 0000000..6504d81 --- /dev/null +++ b/library/src/mipi_syst_api.c @@ -0,0 +1,1314 @@ +/* +Copyright (c) 2018, MIPI Alliance, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ + + /* Internal C-language API implementation */ + +#include "mipi_syst.h" +#include "mipi_syst/message.h" + +#if defined(MIPI_SYST_UNIT_TEST) +#define ASSERT_CHECK(x) ASSERT_EQ(x, true) +#else +#define ASSERT_CHECK(x) +#endif + +#if MIPI_SYST_CONFORMANCE_LEVEL > 10 + +#if !defined(MIPI_SYST_SCATTER_WRITE) +/** + * Default writer access is to call global state systh_writer pointer. + * Redefine this if you can avoid the function pointer overhead. + */ +#define MIPI_SYST_SCATTER_WRITE(syst_handle, scatter_prog, data_ptr) \ + { \ + (syst_handle)->systh_header->systh_writer( \ + (syst_handle), (scatter_prog), (data_ptr));\ + } +#endif + +/** + * predefined write scatter instructions defined in scatter_op table + */ +enum syst_scatter_ops { +#if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID) + SCATTER_OP_GUID, +#endif + +#if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_RECORD) + SCATTER_OP_LOC_FMT, + SCATTER_OP_LOC_32, + SCATTER_OP_LOC_64, +#endif +#if defined(MIPI_SYST_PCFG_LENGTH_FIELD) + SCATTER_OP_LENGTH, +#endif + SCATTER_OP_PAYLD_VAR, + SCATTER_OP_CHECKSUM, + SCATTER_OP_CATID_32, + SCATTER_OP_CATID_64, + SCATTER_OP_CATID_ARGS, + SCATTER_OP_CLOCK, +#if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) + SCATTER_OP_TS, +#endif +#if defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) + SCATTER_OP_VER_ID, + SCATTER_OP_VER_TXT, +#endif + SCATTER_OP_END +}; + +/** + * Scatter instruction that describe the writing of SyS-T message descriptor + * members by the scatter write algorithm. + */ +static const struct mipi_syst_scatter_prog scatter_ops[] = { +#if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID) + + { /* SCATTER_OP_GUID */ + MIPI_SYST_SCATTER_OP_64BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_guid), + 2}, +#endif + +#if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_RECORD) + { /* SCATTER_OP_LOC_FMT */ + MIPI_SYST_SCATTER_OP_8BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_loc.el_format), + 1}, + { /* SCATTER_OP_LOC_32 */ + MIPI_SYST_SCATTER_OP_32BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_loc.el_u), + 1}, + { /* SCATTER_OP_LOC_64 */ + MIPI_SYST_SCATTER_OP_64BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_loc.el_u), + 1}, +#endif +#if defined(MIPI_SYST_PCFG_LENGTH_FIELD) + { /* SCATTER_OP_LENGTH */ + MIPI_SYST_SCATTER_OP_16BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_len), + 1}, +#endif + { /* SCATTER_OP_PAYLD_VAR */ + MIPI_SYST_SCATTER_OP_BLOB, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_var), + 0} + , + { /* SCATTER_OP_PAYLD_CHECKSUM */ + MIPI_SYST_SCATTER_OP_32BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_chk), + 1} + , + { /* SCATTER_OP_CATID_32 */ + MIPI_SYST_SCATTER_OP_32BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_catid.id.sci_32), + 1} + , + { /* SCATTER_OP_CATID_64 */ + MIPI_SYST_SCATTER_OP_64BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_catid.id.sci_64), + 1} + , + { /* SCATTER_OP_CATID_ARGS */ + MIPI_SYST_SCATTER_OP_BLOB, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_catid.param), + 0} + , + { /* SCATTER_OP_CLOCK */ + MIPI_SYST_SCATTER_OP_64BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_clock), + 2} + , +#if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) /* SCATTER_OP_TS */ + { + MIPI_SYST_SCATTER_OP_64BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_ts), + 1} + , +#endif /* defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) */ +#if defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) + { /* SCATTER_OP_VER_ID */ + MIPI_SYST_SCATTER_OP_64BIT, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_version.id), + 1} + , + { /* SCATTER_OP_VER_TXT */ + MIPI_SYST_SCATTER_OP_BLOB, + MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_version.text), + 0} + , +#endif /* defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) */ + + { /* SCATTER_OP_END */ + MIPI_SYST_SCATTER_OP_END, + 0, + 0} +}; + + +/** + * Add optional message components to the message descriptor + */ +static +#if defined(MIPI_SYST_PCFG_ENABLE_INLINE) +MIPI_SYST_CC_INLINE +#endif +void +insert_optional_msg_components(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + mipi_syst_u16 len, + struct mipi_syst_msgdsc *desc, + struct mipi_syst_scatter_prog **prog_ptr) +{ + struct mipi_syst_scatter_prog *prog = *prog_ptr; + +#if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID) + /* origin GUID ? */ + if (0 != desc->ed_tag.et_guid) { + desc->ed_guid = svh->systh_guid; + *prog++ = scatter_ops[SCATTER_OP_GUID]; + } +#endif + +#if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_RECORD) + /* location information ? */ + if ((struct mipi_syst_msglocation*) 0 != loc) { + desc->ed_loc = *loc; + desc->ed_tag.et_location = 1; + + *prog++ = scatter_ops[SCATTER_OP_LOC_FMT]; + if (desc->ed_loc.el_format & 0x1) + *prog++ = scatter_ops[SCATTER_OP_LOC_64]; + else + *prog++ = scatter_ops[SCATTER_OP_LOC_32]; + } +#endif + +#if defined(MIPI_SYST_PCFG_LENGTH_FIELD) + /* pay load length */ + if(0 != desc->ed_tag.et_length) { + desc->ed_len = len; + *prog++ = scatter_ops[SCATTER_OP_LENGTH]; + } +#endif + +#if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) + if (desc->ed_tag.et_timestamp) { + /* timestamp present */ + desc->ed_ts = MIPI_SYST_PLATFORM_CLOCK(); + *prog++ = scatter_ops[SCATTER_OP_TS]; + } +#endif /* defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) */ + + *prog_ptr = prog; +} +#endif + +#if defined(MIPI_SYST_PCFG_ENABLE_STRING_API) + +/** + * Write a string output message + * + * @param svh SyS-T handle + * @param loc Pointer to instrumentation location or null if no location + * @param type string message subtype + * @param severity severity level (0..7) + * @param len number of bytes to emit or 0 to send fixed size 32bytes + * @param str pointer to UTF-8 string bytes + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_write_debug_string(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_subtype_string type, + enum mipi_syst_severity severity, + mipi_syst_u16 len, const char *str) +{ + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + mipi_syst_u64 errmsg; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING; + desc.ed_tag.et_subtype = type; + desc.ed_tag.et_severity = severity; + + if ((const char *)0 == str) { + desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM; + errmsg = +#if defined(MIPI_SYST_BIG_ENDIAN) + 0x286e756c6c290000ull; /* == "(null)\0\0" */ +#else + 0x0000296c6c756e28ull; /* == "(null)\0\0" */ +#endif + str = (char*)&errmsg; + len = 7; + } + insert_optional_msg_components(svh, loc, len, &desc, &prog_ptr); + + desc.ed_pld.data_var = (const mipi_syst_u8 *) str; + *prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR]; + prog_ptr->sso_length = len; + ++prog_ptr; + + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} +#endif /* #if defined(MIPI_SYST_PCFG_ENABLE_STRING_API) */ + +#if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) + +/** + * Write 64-bit catalog message + * + * @param svh SyS-T handle + * @param loc Pointer to instrumentation location or null + * @param severity message severity level (0..7) + * @param catid catalog ID + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_write_catalog64_message(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, mipi_syst_u64 catid) +{ + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + mipi_syst_u16 paramlen; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG; + desc.ed_tag.et_severity = severity; +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P64; +#else + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P32; +#endif + + paramlen = (mipi_syst_u16) + (svh->systh_param_count * sizeof(mipi_syst_u32)); + + insert_optional_msg_components( + svh, loc, + sizeof(catid) + paramlen, + &desc, &prog_ptr); + + /* cat ID */ + desc.ed_pld.data_catid.id.sci_64 = catid; + *prog_ptr++ = scatter_ops[SCATTER_OP_CATID_64]; + + /* parameters (if any) */ + + if (0 != paramlen) { + mipi_syst_u32 *param; + param = svh->systh_param; + desc.ed_pld.data_catid.param = param; + *prog_ptr = scatter_ops[SCATTER_OP_CATID_ARGS]; + prog_ptr->sso_length = paramlen; + ++prog_ptr; +#if defined(MIPI_SYST_BIG_ENDIAN) + while(paramlen) { + *param = MIPI_SYST_HTOLE32(*param); + param++; + paramlen-=sizeof(mipi_syst_u32); + } +#endif + } + + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} + +#endif /* #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) */ + +#if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API) + +/** + * Write 32-Bit catalog message + * + * @param svh SyS-T handle + * @param loc Pointer to instrumentation location or null + * @param severity message severity level (0..7) + * @param catid catalog ID + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_write_catalog32_message(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, mipi_syst_u32 catid) +{ + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + mipi_syst_u16 paramlen; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG; + desc.ed_tag.et_severity = severity; +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P64; +#else + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P32; +#endif + + paramlen = (mipi_syst_u16) + (svh->systh_param_count * sizeof(mipi_syst_u32)); + + insert_optional_msg_components( + svh, loc, + sizeof(catid) + paramlen, + &desc, &prog_ptr); + + /* cat ID */ + desc.ed_pld.data_catid.id.sci_32 = catid; + *prog_ptr++ = scatter_ops[SCATTER_OP_CATID_32]; + + /* parameters (if any) */ + + if (0 != paramlen) { + mipi_syst_u32 * param; + param = svh->systh_param; + desc.ed_pld.data_catid.param = param; + *prog_ptr = scatter_ops[SCATTER_OP_CATID_ARGS]; + prog_ptr->sso_length = paramlen; + ++prog_ptr; +#if defined(MIPI_SYST_BIG_ENDIAN) + while(paramlen) { + *param = MIPI_SYST_HTOLE32(*param); + param++; + paramlen-=sizeof(mipi_syst_u32); + } +#endif + } + + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} + +#endif /* #if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API) */ + +#if defined(MIPI_SYST_PCFG_ENABLE_WRITE_API) + +/** + * Write raw data message + * + * @param svh SyS-T handle + * @param loc pointer to instrumentation location or null + * @param severity message severity level (0..7) + * @param protocol content protocol ID + * @param data pointer to raw data + * @param length number of bytes to send + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_write_raw_message(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, + mipi_syst_u8 protocol, + const void *data, mipi_syst_u16 length) +{ + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_RAW; + desc.ed_tag.et_severity = severity; + desc.ed_tag.et_subtype = protocol; + + insert_optional_msg_components(svh, loc, length, &desc, &prog_ptr); + + desc.ed_pld.data_var = data; + *prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR]; + prog_ptr->sso_length = length; + ++prog_ptr; + + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} +#endif /* defined(MIPI_SYST_PCFG_ENABLE_WRITE_API) */ + +#if defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) + +/** + * Write client build version message + * + * @param svh SyS-T handle + * @param loc pointer to instrumentation location or null + * @param severity message severity level (0..7) + * @param id 64-Bit version ID + * @param text pointer to UTF-8 version text + * @param length number of bytes to send + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_write_build_message(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, + mipi_syst_u64 id, + const char *text, mipi_syst_u16 length) +{ + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_BUILD; + desc.ed_tag.et_severity = severity; + desc.ed_tag.et_subtype = MIPI_SYST_BUILD_ID_LONG; + + insert_optional_msg_components( + svh, loc, length + sizeof(id), &desc, &prog_ptr); + + desc.ed_pld.data_version.id = id; + *prog_ptr = scatter_ops[SCATTER_OP_VER_ID]; + ++prog_ptr; + if (0 != length) { + desc.ed_pld.data_version.text = text; + *prog_ptr = scatter_ops[SCATTER_OP_VER_TXT]; + prog_ptr->sso_length = length; + ++prog_ptr; + } + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} +#endif /* defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) */ + +#if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) +/** +* Write clock sync message +* +* @param svh SyS-T handle +* @param loc pointer to instrumentation location or null +* @param fmt clock sync message subtype +* @param clock_value 64-Bit clock value +* @param clock_freq 64-Bit clock frequency in herz +*/ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_write_clock(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_subtype_clock fmt, + mipi_syst_u64 clock_value, + mipi_syst_u64 clock_freq) +{ + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + prog_ptr = prog; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_subtype = fmt; + desc.ed_tag.et_type = MIPI_SYST_TYPE_CLOCK; + desc.ed_tag.et_severity = MIPI_SYST_SEVERITY_MAX; + + insert_optional_msg_components( + svh, loc, + 2*sizeof(mipi_syst_u64), + &desc, &prog_ptr); + + desc.ed_pld.data_clock[0] = clock_value; + desc.ed_pld.data_clock[1] = clock_freq; + *prog_ptr++ = scatter_ops[SCATTER_OP_CLOCK]; + + *prog_ptr = scatter_ops[SCATTER_OP_END]; + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} + +#endif /* defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) */ + +#if defined(MIPI_SYST_PCFG_ENABLE_PRINTF_API) + +/* printf requires stdarg from the compiler in use. It is a varargs function*/ + +#include <stdarg.h> +#include <stddef.h> +#include <wchar.h> + +#if !defined(MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE) +#define MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE 1024 /* Default 1Kb arg buffer */ +#endif + +/** state IDs of the printf format string parser's finite state machine + */ +enum FmtScanState { + START, + PLAINTEXT, + PERCENT, + FLAGS, + WIDTH, WIDTH_NUMBER, + PRECISION_DOT, PRECISION_VAL, PRECISION_NUMBER, + MODIFIER, + MODIFIER_HALF, + MODIFIER_LONG, + SPECIFIER +}; + +/** format modifier types + */ +enum Modifier { + MOD_NONE, MOD_HH, MOD_H, MOD_L, MOD_LL, MOD_J, MOD_Z, MOD_T, MOD_LD +}; + +/** parser result codes + * + */ +enum ReturnCodes { + FMT_PARSE_OK = 1, + FMT_PARSE_ARG_BUFFER_TOO_SMALL = -1, + FMT_PARSE_UNSUPPORTED_FORMAT = -2 +}; + +/* Helper macro to copy an argument from the arguments into the + * payload buffer. + * + * TOTYPE is the data type that gets stored in the messages's arg buffer + * FROMTYPE is the data type taken from the printf stack via varags + */ +#define COPY_ARG_DOUBLE(TOTYPE, FROMTYPE) \ + do { \ + union {mipi_syst_u64 v; TOTYPE d;} val; \ + val.d = (TOTYPE)va_arg(args, FROMTYPE); \ + if (argp + sizeof(TOTYPE) < argEob) { \ + val.v = MIPI_SYST_HTOLE64(val.v); \ + *((TOTYPE *)argp) = val.d; \ + argp += sizeof(TOTYPE); \ + } else { \ + return FMT_PARSE_ARG_BUFFER_TOO_SMALL; \ + } \ + } while(0) + +#define COPY_ARG32(TOTYPE, FROMTYPE) \ + do { \ + if (argp + sizeof(TOTYPE) < argEob) { \ + *((TOTYPE *)argp) = (TOTYPE)MIPI_SYST_HTOLE32(va_arg(args, FROMTYPE)); \ + argp += sizeof(TOTYPE); \ + } else { \ + return FMT_PARSE_ARG_BUFFER_TOO_SMALL; \ + } \ + } while(0) + +#define COPY_ARG64(TOTYPE, FROMTYPE) \ + do { \ + if (argp + sizeof(TOTYPE) < argEob) { \ + *((TOTYPE *)argp) = (TOTYPE)MIPI_SYST_HTOLE64(va_arg(args, FROMTYPE));\ + argp += sizeof(TOTYPE); \ + } else { \ + return FMT_PARSE_ARG_BUFFER_TOO_SMALL; \ + } \ + } while(0) + +/** Create the payload buffer for a printf format + * + * The payload of a printf message, starts with an UTF-8 string, + * which becomes the printf format. Depending on the format string, further + * parameters follow the format string using the following rules: + * + * All printf arguments follow the format string without alignment bytes added. + * Strings for the '%s' format specifier are embedded as UTF-8 strings with + * 0-byte termination into the payload. + * printf arguments use the binary data layout as defined in the table below. + * + * Data Type | 32 Bit Platform | 64 Bit Platform + * --------------------------|--------------------|--------------------------- + * int, unsigned int | 32 Bits | 32 Bits + * long, unsigned long | 32 Bits | 64 Bits + * long long, unsinged long long|64 Bits | 64 Bits + * size_t | 32 Bits | 64 Bits + * ptrdiff_t | 32 Bits | 64 Bits + * float double, long double | 64 Bits | 64 Bits + * char, unsigned char | 32 Bits | 32 Bits + * wchar_t | 32 Bits | 32 Bits + * Addresses(pointers) | 32 Bits | 64 Bits + * Strings (char *) |UTF-8, 0-terminated | UTF-8, 0-terminated + * + * The format string follows the C99 definition which can contain format + * specifier following this pattern: + * + * %[flags][width][.precision][length]specifier + * + * This function 'only' converts the fmt and arguments into a message payload. + * The actual formatting of the data into a string is done by the receiving + * trace decoder. + * + * @param buffer memory buffer filled with argument data + * @param size # of bytes in buffer + * @param fmt printf format string + * @param args printf varags + + */ +static int buildPrintfPayload( + char * buffer, + mipi_syst_u32 size, + const char * fmt, + va_list args) +{ + char * argEob; + char * argp; + const char * fmtp; + enum FmtScanState state; + enum Modifier modifier; + + if (0 == fmt) return FMT_PARSE_UNSUPPORTED_FORMAT; + + argp = buffer; + argEob = buffer + size; /* end of buffer address */ + fmtp = fmt; + + /* copy argument string to start of payload buffer + */ + while (argp < argEob) { + if( 0 == (*argp++ = *fmtp++)) break; + } + if (argp == argEob) return FMT_PARSE_ARG_BUFFER_TOO_SMALL; + + fmtp = fmt; + state = START; + modifier = MOD_NONE; + + /* loop over the arguments in the format and full the arg buffer + */ + while( *fmtp != 0 ) + { + switch(state) { + case START: + modifier = MOD_NONE; + + state = PLAINTEXT; + ; /* deliberate fall through */ + + case PLAINTEXT: + if (*fmtp == '%') { + state = PERCENT; + } + break; + + case PERCENT: + if (*fmtp == '%') { /* '%%' is not a format, but the % char */ + state = PLAINTEXT; + } else { + /* arg fmt definition is starting */ + state = FLAGS; + continue; + } + break; + + case FLAGS: + switch(*fmtp) { + case '-': + case '+': + case ' ': + case '#': + case '0': + break; + default: + state = WIDTH; + continue; + } + break; + + case WIDTH: + if (*fmtp == '*') { + COPY_ARG32(mipi_syst_s32, int); + state = PRECISION_DOT; + } else { + state = WIDTH_NUMBER; + continue; + } + break; + + case WIDTH_NUMBER: + if (*fmtp < '0' || *fmtp > '9') { /* !isdigit */ + state = PRECISION_DOT; + continue; + } + break; + + case PRECISION_DOT: + if (*fmtp == '.') { + state = PRECISION_VAL; + } else { + state = MODIFIER; + continue; + } + break; + + case PRECISION_VAL: + if (*fmtp == '*') { + COPY_ARG32(mipi_syst_s32, int); + state = MODIFIER; + } else { + state = PRECISION_NUMBER; + continue; + } + break; + + case PRECISION_NUMBER: + if (*fmtp < '0' || *fmtp > '9') { /* !isdigit */ + state = MODIFIER; + continue; + } + break; + + case MODIFIER: + state = SPECIFIER; + + switch(*fmtp){ + case 'h': + modifier = MOD_H; + state = MODIFIER_HALF; + break; + case 'l': + modifier = MOD_L; + state = MODIFIER_LONG; + break; + case 'j': + modifier = MOD_J; + break; + case 'z': + modifier = MOD_Z; + break; + case 't': + modifier = MOD_T; + break; + case 'L': + modifier = MOD_LD; + break; + default: + continue; + } + break; + + case MODIFIER_HALF: + state = SPECIFIER; + if (*fmtp == 'h') { + modifier = MOD_HH; + break; + } else { + continue; + } + break; + + + case MODIFIER_LONG: + state = SPECIFIER; + if (*fmtp == 'l') { + modifier = MOD_LL; + break; + } else { + continue; + } + + case SPECIFIER: + { + switch(*fmtp) { + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + switch(modifier) { + case MOD_L: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_u64, long); +#else + COPY_ARG32(mipi_syst_u32, unsigned long); +#endif + break; + case MOD_LL: + case MOD_J: + COPY_ARG64(mipi_syst_u64, unsigned long long); + break; + case MOD_Z: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_u64, size_t); +#else + COPY_ARG32(mipi_syst_u32, size_t); +#endif + break; + case MOD_T: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_s64, ptrdiff_t); +#else + COPY_ARG32(mipi_syst_s32, ptrdiff_t); +#endif + break; + default: + COPY_ARG32(mipi_syst_u32, unsigned int); + break; + } + state = START; + break; + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + case 'a': + case 'A': + if (modifier == MOD_LD) { + COPY_ARG_DOUBLE(double, long double); /* only double*/ + } else { + COPY_ARG_DOUBLE(double, double); + } + break; + case 'c': + if (modifier == MOD_L) { + COPY_ARG32(mipi_syst_u32, wchar_t); + } else { + COPY_ARG32(mipi_syst_u32, int); + } + break; + case 'p': + case 'n': +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_u64, void *); +#else + COPY_ARG32(mipi_syst_u32, void *); +#endif + break; + case 's': + { + /* Embed string with 0-byte into arg buffer */ + const char * p; + p = va_arg(args, char *); + while (argp < argEob) { + if (0 == (*argp++ = *p++)) { + break; + } + if (argp == argEob) { + return FMT_PARSE_ARG_BUFFER_TOO_SMALL; + } + } + } + break; + + default: + return FMT_PARSE_UNSUPPORTED_FORMAT; + break; + } + state = START; + } + break; + } + ++fmtp; + } + + if (state == START || state == PLAINTEXT) { + return (int)(argp - buffer); + } else { + return FMT_PARSE_UNSUPPORTED_FORMAT; + } +} +#if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) || defined(MIPI_SYST_PCFG_ENABLE_CATID32_API) +static int buildCatalogPayload( + mipi_syst_u8 * buffer, + mipi_syst_u32 size, + va_list args) +{ + mipi_syst_u8 * argEob; + mipi_syst_u8 * argp; + int argType; + + argp = buffer; + argEob = buffer + size; /* end of buffer address */ + + + /* loop over the argument types + */ + for(argType = va_arg(args, int); + argType != 0; + argType = va_arg(args, int)) + { + switch(argType) { + case _MIPI_SYST_CATARG_D: + COPY_ARG32(mipi_syst_u32, unsigned int); + break; + case _MIPI_SYST_CATARG_LD: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_u64, long); +#else + COPY_ARG32(mipi_syst_u32, unsigned long); +#endif + break; + + case _MIPI_SYST_CATARG_LLD: + COPY_ARG64(mipi_syst_u64, unsigned long long); + break; + + case _MIPI_SYST_CATARG_ZD: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_u64, size_t); +#else + COPY_ARG32(mipi_syst_u32, size_t); +#endif + break; + + case _MIPI_SYST_CATARG_TD: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_s64, ptrdiff_t); +#else + COPY_ARG32(mipi_syst_s32, ptrdiff_t); +#endif + break; + + case _MIPI_SYST_CATARG_F: + COPY_ARG_DOUBLE(double, double); + break; + case _MIPI_SYST_CATARG_LF: + COPY_ARG_DOUBLE(double, long double); + break; + case _MIPI_SYST_CATARG_C: + COPY_ARG32(mipi_syst_u32, int); + break; + case _MIPI_SYST_CATARG_HHD: + COPY_ARG32(mipi_syst_u32, int); + break; + case _MIPI_SYST_CATARG_LC: + COPY_ARG32(mipi_syst_u32, wint_t); + break; + + case _MIPI_SYST_CATARG_P: +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + COPY_ARG64(mipi_syst_u64, void *); +#else + COPY_ARG32(mipi_syst_u32, void *); +#endif + break; + + case _MIPI_SYST_CATARG_CSTR: + { + const char * p; + p = va_arg(args, char *); + while (argp < argEob) { + if (0 == (*argp++ = *p++)) { + break; + } + if (argp == argEob) { + return FMT_PARSE_ARG_BUFFER_TOO_SMALL; + } + } + } + break; + + default: + return FMT_PARSE_UNSUPPORTED_FORMAT; + break; + } + } + + return (int)(argp - buffer); +} + +#endif // #if defined(MIPI_SYST_PCFG_ENABLE_CATIDxx_API) + +/** + * Write a printf message + * + * @param svh SyS-T handle + * @param loc Pointer to instrumentation location or null if no location + * @param severity severity level (0..7) + * @param fmt pointer to UTF-8 string bytes + * @param ... optional format arguments + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV + mipi_syst_write_printf_string(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, + const char *fmt, + ...) +{ + char argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE]; + int len; + va_list args; + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + mipi_syst_u64 errmsg; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING; +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + desc.ed_tag.et_subtype = MIPI_SYST_STRING_PRINTF_64; +#else + desc.ed_tag.et_subtype = MIPI_SYST_STRING_PRINTF_32; +#endif + desc.ed_tag.et_severity = severity; + + va_start(args, fmt); + len = buildPrintfPayload(argBuf, sizeof(argBuf), fmt, args); + va_end(args); + + if (len <= 0 ) { + /* Invalid format, send up to 32 bytes from the offending format string + * as string message with tag "invalid parameter" instead + */ + desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM; + errmsg = +#if defined(MIPI_SYST_BIG_ENDIAN) + 0x286e756c6c290000ull; /* == "(null)\0\0" */ +#else + 0x0000296c6c756e28ull; /* == "(null)\0\0" */ +#endif + fmt = fmt ? fmt : (char*)&errmsg; + + for (len = 0; len < 32;) + if (0 == fmt[len++]) break; + } else { + fmt = argBuf; + } + insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr); + + *prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR]; + desc.ed_pld.data_var = (const mipi_syst_u8 *) fmt; + prog_ptr->sso_length = (mipi_syst_u16)len; + ++prog_ptr; + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} + +#if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) + +/** + * Write a printf catalog message with 64bit ID + * + * @param svh SyS-T handle + * @param loc Pointer to instrumentation location or null if no location + * @param severity severity level (0..7) + * @param id catalog id + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV + mipi_syst_write_printf_catalog64(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, + mipi_syst_u64 id, + ...) +{ + mipi_syst_u8 argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE+sizeof(id)]; + int len; + va_list args; + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + mipi_syst_u64 errmsg; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG; +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P64; +#else + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P32; +#endif + desc.ed_tag.et_severity = severity; + + va_start(args, id); + len = buildCatalogPayload(argBuf+sizeof(id), + MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE, + args); + va_end(args); + + if (len < 0 ) { + char * msg; + errmsg = +#if defined(MIPI_SYST_BIG_ENDIAN) + 0x6361746172670000ull; /* = "catarg\0\0" */ +#else + 0x0000677261746163ull; /* = "catarg\0\0" */ +#endif + /* Invalid parameter list */ + desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING; + desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM; + len = 0; + msg = (char*)&errmsg; + while (0 != (argBuf[len++] = *msg++)); + } else { + *(mipi_syst_u64*)argBuf = MIPI_SYST_HTOLE64(id); + len += sizeof(id); + } + + insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr); + + *prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR]; + desc.ed_pld.data_var = (const mipi_syst_u8 *) argBuf; + prog_ptr->sso_length = (mipi_syst_u16)len; + ++prog_ptr; + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} +#endif // #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) +#if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API) + +/** + * Write a printf catalog message with 32bit ID + * + * @param svh SyS-T handle + * @param loc Pointer to instrumentation location or null if no location + * @param severity severity level (0..7) + * @param id catalog id + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV + mipi_syst_write_printf_catalog32(struct mipi_syst_handle* svh, + struct mipi_syst_msglocation* loc, + enum mipi_syst_severity severity, + mipi_syst_u32 id, + ...) +{ + mipi_syst_u8 argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE+sizeof(id)]; + int len; + va_list args; + struct mipi_syst_msgdsc desc; + struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN]; + struct mipi_syst_scatter_prog *prog_ptr = prog; + mipi_syst_u64 errmsg; + + if ((struct mipi_syst_handle*)0 == svh) + return; + + /* assign tag */ + desc.ed_tag = svh->systh_tag; + desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG; +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR) + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P64; +#else + desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P32; +#endif + desc.ed_tag.et_severity = severity; + + va_start(args, id); + len = buildCatalogPayload(argBuf+sizeof(id), + MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE, + args); + va_end(args); + + if (len < 0 ) { + char * msg; + errmsg = +#if defined(MIPI_SYST_BIG_ENDIAN) + 0x6361746172670000ull; /* = "catarg\0\0" */ +#else + 0x0000677261746163ull; /* = "catarg\0\0" */ +#endif + /* Invalid parameter list */ + desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING; + desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM; + len = 0; + msg = (char*)&errmsg; + while (0 != (argBuf[len++] = *msg++)); + } else { + *(mipi_syst_u32*)argBuf = MIPI_SYST_HTOLE32(id); + len += sizeof(id); + } + + insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr); + + *prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR]; + desc.ed_pld.data_var = (const mipi_syst_u8 *) argBuf; + prog_ptr->sso_length = (mipi_syst_u16)len; + ++prog_ptr; + *prog_ptr = scatter_ops[SCATTER_OP_END]; + + ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]); + + /* call IO routine to dump out the message */ + MIPI_SYST_SCATTER_WRITE(svh, prog, &desc); +} +#endif // #if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API) +#endif /* #if defined(MIPI_SYST_PCFG_ENABLE_PRINTF_API) */
\ No newline at end of file diff --git a/library/src/mipi_syst_compiler.c b/library/src/mipi_syst_compiler.c new file mode 100644 index 0000000..a03c1a2 --- /dev/null +++ b/library/src/mipi_syst_compiler.c @@ -0,0 +1,78 @@ +/* +Copyright (c) 2018, MIPI Alliance, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ + + /* Compiler dependent code */ + +#include "mipi_syst.h" + +#if defined(_WIN32) /* MSVC Compiler section */ + +#include <intrin.h> +#pragma intrinsic(_ReturnAddress) + +#if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_ADDRESS) +/** + * Return the instruction pointer address of the instruction + * that follows this function. It is used to compute + * location information for SyS-T instrumentation calls. + * These are the calls that end with the _LOCADDR suffix. + */ +MIPI_SYST_EXPORT void *MIPI_SYST_CALLCONV mipi_syst_return_addr() +{ + return _ReturnAddress(); +} +#endif /* defined(MIPI_SYST_PCFG_ENABLE_LOCATION_ADDRESS) */ + +#elif defined(__GNUC__) /* GNU-C Compiler section */ + +#if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_ADDRESS) +/** + * Return the instruction pointer address of the instruction + * that follows this function. It is used to compute + * location information for SyS-T instrumentation calls. + * These are the calls that end with the _LOCADDR suffix. + */ +MIPI_SYST_EXPORT void *MIPI_SYST_CALLCONV mipi_syst_return_addr() +{ + return __builtin_return_address(0); +} +#endif + +#else +#error unknown compiler, copy and adapt one of the sections above +#endif
\ No newline at end of file diff --git a/library/src/mipi_syst_crc32.c b/library/src/mipi_syst_crc32.c new file mode 100644 index 0000000..65e3451 --- /dev/null +++ b/library/src/mipi_syst_crc32.c @@ -0,0 +1,313 @@ +/* +Copyright (c) 2018, MIPI Alliance, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ + +#include "mipi_syst.h" + +#if defined(MIPI_SYST_PCFG_ENABLE_CHECKSUM) && !defined(MIPI_SYST_CRC_INTRINSIC) + +/* + * Pre-computed CRC-C values for all 8-bit values using + * polynomial 0x1EDC6F41 (Castagnoli). + */ + +const mipi_syst_u32 mipi_syst_crc_table[256] = { + 0x00000000, + 0xF26B8303, + 0xE13B70F7, + 0x1350F3F4, + 0xC79A971F, + 0x35F1141C, + 0x26A1E7E8, + 0xD4CA64EB, + 0x8AD958CF, + 0x78B2DBCC, + 0x6BE22838, + 0x9989AB3B, + 0x4D43CFD0, + 0xBF284CD3, + 0xAC78BF27, + 0x5E133C24, + 0x105EC76F, + 0xE235446C, + 0xF165B798, + 0x030E349B, + 0xD7C45070, + 0x25AFD373, + 0x36FF2087, + 0xC494A384, + 0x9A879FA0, + 0x68EC1CA3, + 0x7BBCEF57, + 0x89D76C54, + 0x5D1D08BF, + 0xAF768BBC, + 0xBC267848, + 0x4E4DFB4B, + 0x20BD8EDE, + 0xD2D60DDD, + 0xC186FE29, + 0x33ED7D2A, + 0xE72719C1, + 0x154C9AC2, + 0x061C6936, + 0xF477EA35, + 0xAA64D611, + 0x580F5512, + 0x4B5FA6E6, + 0xB93425E5, + 0x6DFE410E, + 0x9F95C20D, + 0x8CC531F9, + 0x7EAEB2FA, + 0x30E349B1, + 0xC288CAB2, + 0xD1D83946, + 0x23B3BA45, + 0xF779DEAE, + 0x05125DAD, + 0x1642AE59, + 0xE4292D5A, + 0xBA3A117E, + 0x4851927D, + 0x5B016189, + 0xA96AE28A, + 0x7DA08661, + 0x8FCB0562, + 0x9C9BF696, + 0x6EF07595, + 0x417B1DBC, + 0xB3109EBF, + 0xA0406D4B, + 0x522BEE48, + 0x86E18AA3, + 0x748A09A0, + 0x67DAFA54, + 0x95B17957, + 0xCBA24573, + 0x39C9C670, + 0x2A993584, + 0xD8F2B687, + 0x0C38D26C, + 0xFE53516F, + 0xED03A29B, + 0x1F682198, + 0x5125DAD3, + 0xA34E59D0, + 0xB01EAA24, + 0x42752927, + 0x96BF4DCC, + 0x64D4CECF, + 0x77843D3B, + 0x85EFBE38, + 0xDBFC821C, + 0x2997011F, + 0x3AC7F2EB, + 0xC8AC71E8, + 0x1C661503, + 0xEE0D9600, + 0xFD5D65F4, + 0x0F36E6F7, + 0x61C69362, + 0x93AD1061, + 0x80FDE395, + 0x72966096, + 0xA65C047D, + 0x5437877E, + 0x4767748A, + 0xB50CF789, + 0xEB1FCBAD, + 0x197448AE, + 0x0A24BB5A, + 0xF84F3859, + 0x2C855CB2, + 0xDEEEDFB1, + 0xCDBE2C45, + 0x3FD5AF46, + 0x7198540D, + 0x83F3D70E, + 0x90A324FA, + 0x62C8A7F9, + 0xB602C312, + 0x44694011, + 0x5739B3E5, + 0xA55230E6, + 0xFB410CC2, + 0x092A8FC1, + 0x1A7A7C35, + 0xE811FF36, + 0x3CDB9BDD, + 0xCEB018DE, + 0xDDE0EB2A, + 0x2F8B6829, + 0x82F63B78, + 0x709DB87B, + 0x63CD4B8F, + 0x91A6C88C, + 0x456CAC67, + 0xB7072F64, + 0xA457DC90, + 0x563C5F93, + 0x082F63B7, + 0xFA44E0B4, + 0xE9141340, + 0x1B7F9043, + 0xCFB5F4A8, + 0x3DDE77AB, + 0x2E8E845F, + 0xDCE5075C, + 0x92A8FC17, + 0x60C37F14, + 0x73938CE0, + 0x81F80FE3, + 0x55326B08, + 0xA759E80B, + 0xB4091BFF, + 0x466298FC, + 0x1871A4D8, + 0xEA1A27DB, + 0xF94AD42F, + 0x0B21572C, + 0xDFEB33C7, + 0x2D80B0C4, + 0x3ED04330, + 0xCCBBC033, + 0xA24BB5A6, + 0x502036A5, + 0x4370C551, + 0xB11B4652, + 0x65D122B9, + 0x97BAA1BA, + 0x84EA524E, + 0x7681D14D, + 0x2892ED69, + 0xDAF96E6A, + 0xC9A99D9E, + 0x3BC21E9D, + 0xEF087A76, + 0x1D63F975, + 0x0E330A81, + 0xFC588982, + 0xB21572C9, + 0x407EF1CA, + 0x532E023E, + 0xA145813D, + 0x758FE5D6, + 0x87E466D5, + 0x94B49521, + 0x66DF1622, + 0x38CC2A06, + 0xCAA7A905, + 0xD9F75AF1, + 0x2B9CD9F2, + 0xFF56BD19, + 0x0D3D3E1A, + 0x1E6DCDEE, + 0xEC064EED, + 0xC38D26C4, + 0x31E6A5C7, + 0x22B65633, + 0xD0DDD530, + 0x0417B1DB, + 0xF67C32D8, + 0xE52CC12C, + 0x1747422F, + 0x49547E0B, + 0xBB3FFD08, + 0xA86F0EFC, + 0x5A048DFF, + 0x8ECEE914, + 0x7CA56A17, + 0x6FF599E3, + 0x9D9E1AE0, + 0xD3D3E1AB, + 0x21B862A8, + 0x32E8915C, + 0xC083125F, + 0x144976B4, + 0xE622F5B7, + 0xF5720643, + 0x07198540, + 0x590AB964, + 0xAB613A67, + 0xB831C993, + 0x4A5A4A90, + 0x9E902E7B, + 0x6CFBAD78, + 0x7FAB5E8C, + 0x8DC0DD8F, + 0xE330A81A, + 0x115B2B19, + 0x020BD8ED, + 0xF0605BEE, + 0x24AA3F05, + 0xD6C1BC06, + 0xC5914FF2, + 0x37FACCF1, + 0x69E9F0D5, + 0x9B8273D6, + 0x88D28022, + 0x7AB90321, + 0xAE7367CA, + 0x5C18E4C9, + 0x4F48173D, + 0xBD23943E, + 0xF36E6F75, + 0x0105EC76, + 0x12551F82, + 0xE03E9C81, + 0x34F4F86A, + 0xC69F7B69, + 0xD5CF889D, + 0x27A40B9E, + 0x79B737BA, + 0x8BDCB4B9, + 0x988C474D, + 0x6AE7C44E, + 0xBE2DA0A5, + 0x4C4623A6, + 0x5F16D052, + 0xAD7D5351 +}; + + +#if !defined(MIPI_SYST_PCFG_ENABLE_INLINE) +#define MIPI_SYST_PCFG_ENABLE_INLINE +#include "mipi_syst/crc32.h" +#endif + +#endif /* defined(MIPI_SYST_PCFG_ENABLE_CHECKSUM) && !defined(MIPI_SYST_CRC_INTRINSIC)) */
\ No newline at end of file diff --git a/library/src/mipi_syst_init.c b/library/src/mipi_syst_init.c new file mode 100644 index 0000000..90ba5a5 --- /dev/null +++ b/library/src/mipi_syst_init.c @@ -0,0 +1,204 @@ +/* +Copyright (c) 2018, MIPI Alliance, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ + +#include "mipi_syst.h" +#include "mipi_syst/message.h" + +/** + * SyS-T global state + */ +static struct mipi_syst_header syst_hdr = { 0 }; + +static union mipi_syst_null_init { + struct mipi_syst_handle handle; + struct mipi_syst_header header; +} zero = { {0} }; /* for initializations */ + +#if !defined(MIPI_SYST_PCFG_ENABLE_DEFAULT_SCATTER_WRITE) +/** + * null-device style default output function + */ +static void nullWriter(struct mipi_syst_handle* systh, + struct mipi_syst_scatter_prog scatterprog, const void *pdesc) +{ +} +#endif + +/** + * Initialize the SyS-T library. + * + * This function must be called during the start of the platform before any + * other instrumentation library call. The function initializes the global + * state data necessary for the library to execute. Passing NULL as state + * means using the shared global state singleton. Passing a valid pointer + * allows using multiple SyS-T state context structures in parallel. + * + * @param header Pointer to SyS-T global state structure or NULL for default. + * @param pfinit Pointer to platform initialization function or 0 if not used. + * @param init_param Value passed to the the platform init hook function. + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_init( + struct mipi_syst_header* header, + mipi_syst_inithook_t pfinit, + const void *init_param) +{ + if (0 == header) { + /* No user supplied global state storage, + * use internal default state + */ + header = &syst_hdr; + } + + *header = zero.header; + header->systh_version = MIPI_SYST_VERSION_CODE; + +#if MIPI_SYST_CONFORMANCE_LEVEL > 10 +#if defined(MIPI_SYST_PCFG_ENABLE_DEFAULT_SCATTER_WRITE) + header->systh_writer = mipi_syst_scatter_write; +#else + header->systh_writer = nullWriter; +#endif +#endif + + /* call platform state initialization hook if defined + */ + if ((mipi_syst_inithook_t) 0 != pfinit) + (*pfinit) (header, init_param); +} + +/** + * Destroy the SyS-T library state. + * + * This function must be called during shutdown of the platform to release + * any SyS-T resources. + * + * @param header Pointer to library state or NULL to use shared default. + * @param pfdestroy Pointer to platform state destroy function or 0 + * if not used. + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV +mipi_syst_destroy(struct mipi_syst_header* header, mipi_syst_destroyhook_t pfdestroy) +{ + if (0 == header) { + /* No user supplied global state storage, + * use internal default state + */ + header = &syst_hdr; + } + + /* call platform state destroy hook first, if defined + */ + if ((mipi_syst_destroyhook_t) 0 != pfdestroy) + (*pfdestroy) (header); +} + +/** + * Initialize a SyS-T handle. + * + * @param header Pointer to library state or NULL to use shared default. + * @param svh Pointer to new/uninitialized SyS-T handle + * @param origin Value passed to the the platform handle init function + * @param fromHeap 1 of heap allocated handle, 0 otherwise + */ +MIPI_SYST_EXPORT struct mipi_syst_handle* MIPI_SYST_CALLCONV +mipi_syst_init_handle( + struct mipi_syst_header* header, + struct mipi_syst_handle* svh, + const struct mipi_syst_origin *origin, + mipi_syst_u32 fromHeap) +{ + if ((struct mipi_syst_handle*) 0 == svh) + return svh; + + + if (0 == header) { + /* No user supplied global state storage, + * use internal default state + */ + header = &syst_hdr; + } + + *svh = zero.handle; + + svh->systh_header = header; + svh->systh_flags.shf_alloc = fromHeap ? 1 : 0; + +#if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID) + + if (0 != origin) + { + MIPI_SYST_SET_HANDLE_ORIGIN(svh, *origin); + } +#endif + + /* call platform handle initialization hook if defined + */ +#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA) + if ((mipi_syst_inithandle_hook_t) 0 != svh->systh_header->systh_inith) + svh->systh_header->systh_inith(svh); +#endif + return svh; +} + +/** + * Release a SyS-T handle. + * + * @param svh Pointer to initialized SyS-T handle + */ +MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV mipi_syst_delete_handle(struct mipi_syst_handle* svh) +{ + if ((struct mipi_syst_handle*) 0 != svh) { +#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA) + /* call platform handle release hook if defined + */ + if ((mipi_syst_releasehandle_hook_t) 0 != + svh->systh_header->systh_releaseh) + svh->systh_header->systh_releaseh(svh); +#endif + +#if defined(MIPI_SYST_PCFG_ENABLE_HEAP_MEMORY) + if (0 != svh->systh_flags.shf_alloc) { + MIPI_SYST_HEAP_FREE(svh); + } else +#endif + { + *svh = zero.handle; + } + } +}
\ No newline at end of file diff --git a/library/src/mipi_syst_inline.c b/library/src/mipi_syst_inline.c new file mode 100644 index 0000000..ca22ef0 --- /dev/null +++ b/library/src/mipi_syst_inline.c @@ -0,0 +1,48 @@ +/* +Copyright (c) 2018, MIPI Alliance, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ + +#include "mipi_syst.h" + +/* Include inline function in this cpp file if functions inline + * support is disabled by the platform define + * MIPI_SYST_PCFG_ENABLE_INLINE. + * Implementation will then use true functions to save code space. + */ +#if !defined(MIPI_SYST_PCFG_ENABLE_INLINE) +#include "mipi_syst/inline.h" +#endif
\ No newline at end of file diff --git a/library/src/mipi_syst_writer.c b/library/src/mipi_syst_writer.c new file mode 100644 index 0000000..3120ff3 --- /dev/null +++ b/library/src/mipi_syst_writer.c @@ -0,0 +1,219 @@ +/* +Copyright (c) 2018, MIPI Alliance, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ +#include "mipi_syst.h" +#include "mipi_syst/message.h" +#include "mipi_syst/crc32.h" + +#if defined(MIPI_SYST_PCFG_ENABLE_DEFAULT_SCATTER_WRITE) + + /** scatter write routine + * + * This function implements the scatter write algorithm that translates + * the logical SyS-T memory descriptor representation into output + * requests. The actual output routines are defined through + * the MIPI_SYST_OUTPUT_* definitions from the platform header file. + * + * @param systh used syst handle + * @param scatterprog message content write instructions + * @param pdesc pointer to memory area with message data + */ +void mipi_syst_scatter_write(struct mipi_syst_handle* systh, + struct mipi_syst_scatter_prog *scatterprog, const void *pdesc) +{ + unsigned int repeat; + + /* Define an "any" size integer pointer to avoid casts and to simplify + * type based incrementing + */ + union { + const void *vp; + const mipi_syst_u8 *bp; + const mipi_syst_u16 *hp; + const mipi_syst_u32 *wp; + const mipi_syst_u64 *dp; + } data; + +#if defined(MIPI_SYST_PCFG_ENABLE_CHECKSUM) +#define IFDO(a, b) { if (a) do { b; } while (0); } + + mipi_syst_u32 crc; + int use_crc; + + use_crc = systh->systh_tag.et_chksum; + crc = MIPI_SYST_CRC32_INIT(0); +#else + +#define IFDO(a, b) + /* no checksump computation support */ +#endif + + /* Write the "always" present tag field as a time-stamped D32 */ + MIPI_SYST_OUTPUT_D32TS(systh, *(mipi_syst_u32 *)pdesc); + + IFDO(use_crc, MIPI_SYST_CRC32_U32(crc, *(mipi_syst_u32 *)pdesc)); + + /* Run the message scatter write program to dump the message contents + */ + while (scatterprog->sso_opcode != MIPI_SYST_SCATTER_OP_END) { + repeat = scatterprog->sso_length; + data.vp = pdesc; + data.bp += scatterprog->sso_offset; + + switch (scatterprog->sso_opcode) { + case MIPI_SYST_SCATTER_OP_8BIT: + do { + MIPI_SYST_OUTPUT_D8(systh, *data.bp); + IFDO(use_crc, + MIPI_SYST_CRC32_U8(crc, *data.bp)); + ++data.bp; + } while (--repeat); + break; + + case MIPI_SYST_SCATTER_OP_16BIT: + do { + MIPI_SYST_OUTPUT_D16(systh, *data.hp); + IFDO(use_crc, + MIPI_SYST_CRC32_U16(crc, *data.hp)); + ++data.hp; + } while (--repeat); + break; + + case MIPI_SYST_SCATTER_OP_32BIT: + do { + MIPI_SYST_OUTPUT_D32(systh, *data.wp); + IFDO(use_crc, + MIPI_SYST_CRC32_U32(crc, *data.wp)); + ++data.wp; + } while (--repeat); + break; + + + case MIPI_SYST_SCATTER_OP_64BIT: + do { +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO) + MIPI_SYST_OUTPUT_D64(systh, *data.dp); +#else +#if defined(MIPI_SYST_BIG_ENDIAN) + MIPI_SYST_OUTPUT_D32(systh, data.wp[1]); + MIPI_SYST_OUTPUT_D32(systh, data.wp[0]); +#else + MIPI_SYST_OUTPUT_D32(systh, data.wp[0]); + MIPI_SYST_OUTPUT_D32(systh, data.wp[1]); +#endif + +#endif /* ! defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO) */ + IFDO(use_crc, + MIPI_SYST_CRC32_U64(crc, *data.dp)); + ++data.dp; + } while (--repeat); + break; + + case MIPI_SYST_SCATTER_OP_BLOB: + /* data location is pointer to real data, + * not data itself + */ + data.vp = *(void **)data.vp; + +#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO) + + while (repeat >= sizeof(mipi_syst_u64)) { + mipi_syst_u64 v; + v = MIPI_SYST_HTOLE64(*data.dp); + MIPI_SYST_OUTPUT_D64(systh, v); + IFDO(use_crc, + MIPI_SYST_CRC32_U64(crc, v)); + ++data.dp; + repeat -= sizeof(mipi_syst_u64); + } + + if (repeat >= sizeof(mipi_syst_u32)) { + mipi_syst_u32 v; + v = MIPI_SYST_HTOLE32(*data.wp); + MIPI_SYST_OUTPUT_D32(systh, v); + IFDO(use_crc, + MIPI_SYST_CRC32_U32(crc, + *data.wp)); + ++data.wp; + repeat -= sizeof(mipi_syst_u32); + } +#else + while (repeat >= sizeof(mipi_syst_u32)) { + mipi_syst_u32 v; + v = MIPI_SYST_HTOLE32(*data.wp); + MIPI_SYST_OUTPUT_D32(systh, v); + + IFDO(use_crc, + MIPI_SYST_CRC32_U32(crc, v)); + ++data.wp; + repeat -= sizeof(mipi_syst_u32); + } +#endif + if (repeat >= sizeof(mipi_syst_u16)) { + mipi_syst_u16 v; + v = MIPI_SYST_HTOLE16(*data.hp); + MIPI_SYST_OUTPUT_D16(systh, v); + + IFDO(use_crc, + MIPI_SYST_CRC32_U16(crc, v)); + ++data.hp; + repeat -= sizeof(mipi_syst_u16); + } + + if (repeat) { + MIPI_SYST_OUTPUT_D8(systh, + *data.bp); + IFDO(use_crc, + MIPI_SYST_CRC32_U8(crc, *data.bp)); + } + break; + } + ++scatterprog; + } + +#if defined(MIPI_SYST_PCFG_ENABLE_CHECKSUM) + if (use_crc) { + crc = MIPI_SYST_CRC32_GET(crc); + MIPI_SYST_OUTPUT_D32(systh, crc); + } +#endif + + /* EVENT end of record mark */ + MIPI_SYST_OUTPUT_FLAG(systh); +} + +#endif /* defined(MIPI_SYST_PCFG_ENABLE_DEFAULT_SCATTER_WRITE) */
\ No newline at end of file |