1 /*
2 Copyright (c) 2018, MIPI Alliance, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 * Neither the name of the copyright holder nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Contributors:
36 * Norbert Schulz (Intel Corporation) - Initial API and implementation
37 */
38
39 #include <stdio.h>
40 #if defined(_WIN32)
41 #include <windows.h>
42 #else
43 #include <sys/time.h>
44 #endif
45
46 #include "mipi_syst.h"
47
48 /* "driver" data output routines */
49 static void write_d32mts(struct mipi_syst_handle* systh, mipi_syst_u32 v);
50 static void write_d64mts(struct mipi_syst_handle* systh, mipi_syst_u64 v);
51 static void write_d32ts(struct mipi_syst_handle* systh, mipi_syst_u32 v);
52 static void write_d8(struct mipi_syst_handle* systh, mipi_syst_u8 v);
53 static void write_d16(struct mipi_syst_handle* systh, mipi_syst_u16 v);
54 static void write_d32(struct mipi_syst_handle* systh, mipi_syst_u32 v);
55 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
56 static void write_d64(struct mipi_syst_handle* systh, mipi_syst_u64 vp);
57 #endif
58 static void write_flag(struct mipi_syst_handle* systh);
59
60 /**
61 * Platform specific SyS-T handle initialization hook function
62 *
63 * @param systh pointer to the new SyS-T handle structure
64 */
platform_handle_init(struct mipi_syst_handle * systh)65 static void platform_handle_init(struct mipi_syst_handle* systh)
66 {
67 #if !defined(MIPI_SYST_UNIT_TEST)
68 printf(
69 " in SyS-T platform handle init hook: systh = %p\n\n",
70 systh
71 );
72 #endif
73
74 /* Initialize platform specific data in global state
75 * This example just stores the platform_data, a real implementation
76 * would put data into the handle structure that enables the output
77 * routines to execute efficiently (pointer for MMIO for example).
78 */
79 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
80
81 #endif
82 }
83
84 /**
85 * Platform specific SyS-T handle initialization hook function
86 *
87 * @param systh pointer to the new SyS-T handle structure
88 */
platform_handle_release(struct mipi_syst_handle * systh)89 static void platform_handle_release(struct mipi_syst_handle* systh)
90 {
91 #if !defined(MIPI_SYST_UNIT_TEST) && defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
92 printf(
93 " in SyS-T platform handle release hook:systh = %p\n",
94 systh
95 );
96 #endif
97
98 /* Release any handle specific data or resources here.*/
99 }
100
101 /**
102 * Platform specific global state initialization hook function
103 *
104 * @param systh pointer to the new SyS-T handle structure
105 * @param platform_data user defined data for the init function.
106 */
107 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_platform_init(struct mipi_syst_header * systh,const void * platform_data)108 mipi_syst_platform_init(struct mipi_syst_header* systh, const void * platform_data)
109 {
110 #if !defined(MIPI_SYST_UNIT_TEST)
111 printf(
112 " in SyS-T platform init hook: \"mipi_syst_platform_state_init()\"\n"
113 " systh = %p, platform_data = %p\n",
114 systh,
115 platform_data
116 );
117 #endif
118
119 /* Set handle init hook that performs per SyS-T handle initialization
120 * and destruction
121 */
122 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
123 systh->systh_inith = platform_handle_init;
124 systh->systh_releaseh = platform_handle_release;
125 #endif
126
127 /* Initialize platform specific data in global state
128 * This platform example puts its low level output function
129 * pointers here. A real implementation may have these "inlined"
130 * for performance reasons.
131 */
132 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA)
133 systh->systh_platform.write_d32ts = write_d32ts;
134 systh->systh_platform.write_d32mts = write_d32mts;
135 systh->systh_platform.write_d64mts = write_d64mts;
136 systh->systh_platform.write_d8 = write_d8;
137 systh->systh_platform.write_d16 = write_d16;
138 systh->systh_platform.write_d32 = write_d32;
139 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
140 systh->systh_platform.write_d64 = write_d64;
141 #endif
142 systh->systh_platform.write_flag = write_flag;
143 #endif
144 }
145
146 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_platform_destroy(struct mipi_syst_header * systh)147 mipi_syst_platform_destroy(struct mipi_syst_header* systh)
148 {
149 (void)systh;
150 }
151
152 #if !defined(MIPI_SYST_STATIC)
153 /**
154 * This example platform uses SyS-T as a shared library inside an
155 * application. The platform init hook is called during a shared library
156 * constructor call.
157 */
shared_library_init()158 static MIPI_SYST_SHAREDLIB_CONSTRUCTOR void shared_library_init()
159 {
160 /* Initialize SyS-T infrastructure
161 * This must be done once at platform startup.
162 * The parameters are the platform specific initialization function and
163 * the data that gets passed to it.
164 */
165 printf("calling MIPI_SYST_INIT() from platform code \n");
166 MIPI_SYST_INIT(mipi_syst_platform_init, (void*)42);
167 }
168
169 /**
170 * This example platform uses SyS-T as a shared library inside an
171 * application. The platform destroy hook is called during a shared library
172 * destructor call.
173 */
shared_library_exit()174 static MIPI_SYST_SHAREDLIB_DESTRUCTOR void shared_library_exit()
175 {
176 /* run platform shutdown code */
177 MIPI_SYST_SHUTDOWN(mipi_syst_platform_destroy);
178 printf("\nexecuted MIPI_SYST_SHUTDOWN() from platform code \n");
179 }
180
181 #if defined(_WIN32)
182 /**
183 * Windows DLL main routine, needed to run the global initialization and
184 * destruction handlers.
185 */
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved)186 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
187 {
188 (void)lpReserved;
189 (void)hinstDLL;
190
191 switch (fdwReason) {
192 case DLL_PROCESS_ATTACH:
193 shared_library_init();
194 break;
195 case DLL_PROCESS_DETACH:
196 shared_library_exit();
197 break;
198 }
199 return TRUE;
200 }
201 #endif
202 #endif /* !defined(MIPI_SYST_STATIC) */
203
204 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
205
206 /* Save a message bytes for printing the raw message when completed.
207 */
append_raw(struct mipi_syst_handle * systh,const void * p,int n)208 static void append_raw(
209 struct mipi_syst_handle* systh,
210 const void * p,
211 int n)
212 {
213 int i;
214
215 #if defined(MIPI_SYST_BIG_ENDIAN)
216 for (i = n-1; i >= 0; --i) {
217 #else
218 for (i = 0; i < n; ++i) {
219 #endif
220 mipi_syst_u32 index = systh->systh_platform.sph_raw_count++;
221 if (index < sizeof(systh->systh_platform.sph_raw)) {
222 systh->systh_platform.sph_raw[index] =
223 ((const mipi_syst_u8*)p)[i];
224 }
225 else {
226 fprintf(stderr, "Internal Error: Record buffer overflow\n");
227 break;
228 }
229 }
230 }
231 #endif
232
233 /* dump contents for raw message bytes
234 */
235 static void write_rawdata(struct mipi_syst_handle* systh)
236 {
237 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
238 static char valToHex[] = "0123456789ABCDEF";
239 const mipi_syst_u8 *p;
240
241 printf("SYS-T RAW DATA: ");
242 for (p = systh->systh_platform.sph_raw;
243 systh->systh_platform.sph_raw_count;
244 ++p, --systh->systh_platform.sph_raw_count)
245 {
246 putc(valToHex[(*p) >> 0x4], stdout);
247 putc(valToHex[(*p) & 0xF], stdout);
248 }
249 #endif
250 }
251
252 /* Dummy driver output routines that just print their operation.
253 */
254 static void write_d32mts(struct mipi_syst_handle* systh, mipi_syst_u32 v)
255 {
256 /* d32mts == Short SyS-T header, reset io count
257 */
258 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
259 systh->systh_platform.sph_io_count = 0;
260 systh->systh_platform.sph_raw_count = 0;
261
262
263 printf("STP Protocol Output:\n");
264
265 printf(" %2d <D32MTS> %08x\n",
266 systh->systh_platform.sph_io_count++, v);
267
268 append_raw(systh, &v, sizeof(v));
269 write_rawdata(systh);
270 printf("\n\n");
271 #endif
272 }
273 static void write_d64mts(struct mipi_syst_handle* systh, mipi_syst_u64 v)
274 {
275 /* d64mts == 64-Bit Short SyS-T header, reset io count
276 */
277 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
278 systh->systh_platform.sph_io_count = 0;
279
280 printf("STP Protocol Output:\n");
281
282 printf(" %2d <D64MTS> %08llx\n",
283 systh->systh_platform.sph_io_count++, v);
284
285 append_raw(systh, &v, sizeof(v));
286 write_rawdata(systh);
287 printf("\n\n");
288
289 #endif
290 }
291
292 static void write_d32ts(struct mipi_syst_handle* systh, mipi_syst_u32 v)
293 {
294 /* d32ts == SyS-T header, reset io count
295 */
296 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
297 systh->systh_platform.sph_io_count = 0;
298
299 printf("STP Protocol Output:\n");
300
301 printf(" %2d <D32TS> %08x\n",
302 systh->systh_platform.sph_io_count++, v);
303
304 append_raw(systh, &v, sizeof(v));
305 #endif
306 }
307 static void write_d8(struct mipi_syst_handle* systh, mipi_syst_u8 v)
308 {
309 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
310 printf(" %2d <D8> %02x\n",
311 systh->systh_platform.sph_io_count++, v);
312
313 append_raw(systh, &v, sizeof(v));
314 #endif
315 }
316
317 static void write_d16(struct mipi_syst_handle* systh, mipi_syst_u16 v)
318 {
319 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
320 printf(" %2d <D16> %04x\n",
321 systh->systh_platform.sph_io_count++, v);
322
323 append_raw(systh, &v, sizeof(v));
324 #endif
325 }
326
327 static void write_d32(struct mipi_syst_handle* systh, mipi_syst_u32 v)
328 {
329 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
330 printf(" %2d <D32> %08x\n",
331 systh->systh_platform.sph_io_count++, v);
332
333 append_raw(systh, &v, sizeof(v));
334 #endif
335 }
336
337 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
338 static void write_d64(struct mipi_syst_handle* systh, mipi_syst_u64 v)
339 {
340 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
341 printf(" %2d <D64> %08x%08x\n",
342 systh->systh_platform.sph_io_count++,
343 #if defined(MIPI_SYST_BIG_ENDIAN)
344 (mipi_syst_u32)v, (mipi_syst_u32)(v >> 32);
345 #else
346 (mipi_syst_u32)(v >> 32), (mipi_syst_u32)v);
347 #endif
348 #endif
349 append_raw(systh, &v, sizeof(v));
350 }
351 #endif
352
353 static void write_flag(struct mipi_syst_handle* systh)
354 {
355 #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
356 printf(" %2d <FLAG>\n", systh->systh_platform.sph_io_count++);
357
358 write_rawdata(systh);
359 printf("\n\n");
360
361 #endif
362 }
363
364 MIPI_SYST_EXPORT
365 mipi_syst_u64 MIPI_SYST_CALLCONV mipi_syst_get_epoch_us()
366 {
367 mipi_syst_u64 epoch;
368 #if defined(MIPI_SYST_UNIT_TEST)
369 epoch = 0x12345678aabbccddull;
370 #elif defined(_WIN32)
371 // Windows does not offer epoch time API directly.
372 // Search for the 116444... constant below on
373 // MSDN for an explanation of the computation:
374 //
375 FILETIME ft;
376 GetSystemTimeAsFileTime(&ft);
377 epoch = ft.dwHighDateTime;
378 epoch = ((epoch << 32) | ft.dwLowDateTime) / 10 - 11644473600000000ULL;
379
380 #else
381 struct timeval tv;
382
383 gettimeofday(&tv, NULL);
384 epoch = tv.tv_sec;
385 epoch *= 1000000;
386 epoch += tv.tv_usec;
387 #endif
388 return epoch;
389 }
390
391 #if defined(MIPI_SYST_PCFG_ENABLE_HEAP_MEMORY)
392 MIPI_SYST_EXPORT
393 void * MIPI_SYST_CALLCONV mipi_syst_platform_alloc(size_t s)
394 {
395 return malloc(s);
396 }
397
398 MIPI_SYST_EXPORT
399 void MIPI_SYST_CALLCONV mipi_syst_platform_free(void * p)
400 {
401 free(p);
402 }
403
404 #endif /* defined(MIPI_SYST_PCFG_ENABLE_HEAP_MEMORY) */