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) */