1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24cc Tests.c -o /tmp/tests -framework IOKit -Wno-four-char-constants  -g
25*/
26
27#include <ctype.h>
28#include <stdlib.h>
29#include <assert.h>
30#include <limits.h>
31
32
33#include <mach/mach_interface.h>
34#include <mach/vm_region.h>
35#include <mach/thread_switch.h>
36
37
38/*
39 */
40
41
42#include <mach/clock_types.h>
43#include <IOKit/IOKitLib.h>
44#include <IOKit/hidsystem/IOHIDShared.h>
45//#include <dev/evio.h>
46#include <IOKit/graphics/IOFramebufferShared.h>
47
48#include <IOKit/graphics/IOGraphicsEngine.h>
49
50EvGlobals * 	evg;
51StdFBShmem_t *  fbshmem;
52mach_port_t	masterPort;
53unsigned int	clock_freq;
54
55/*
56 */
57
58inline UInt64 CFReadTSR() {
59    union {
60	UInt64 time64;
61	UInt32 word[2];
62    } now;
63
64    /* Read from PowerPC 64-bit time base register. The increment */
65    /* rate of the time base is implementation-dependent, but is */
66    /* 1/4th the bus clock cycle on 603/604/750 processors. */
67    UInt32 t3;
68#ifdef __ppc__
69    do {
70	__asm__ volatile("mftbu %0" : "=r" (now.word[0]));
71	__asm__ volatile("mftb %0" : "=r" (now.word[1]));
72	__asm__ volatile("mftbu %0" : "=r" (t3));
73    } while (now.word[0] != t3);
74#endif
75
76    return now.time64;
77}
78
79void getClockFrequency( void )
80{
81    kern_return_t	kr;
82    unsigned int	size;
83    io_registry_entry_t	root;
84
85    assert( (
86    root = IORegistryEntryFromPath( masterPort, "IODeviceTree:/" )
87    ));
88
89    size = sizeof( clock_freq );
90    assert( KERN_SUCCESS == (
91    kr = IORegistryEntryGetProperty( root, "clock-frequency", (char *)&clock_freq, &size )
92    ));
93    assert( size == sizeof( clock_freq ));
94
95    printf("clock-frequency = %d\n", clock_freq);
96
97    IOObjectRelease( root );
98}
99
100void printElapsed( UInt64 start, UInt64 end )
101{
102#define numer 1000
103#define divisor 1000
104    printf("elapsed %d us\n", (int)((end - start) / (clock_freq / divisor / 4 ) * numer ));
105}
106
107void AccelTests( int reset, int count )
108{
109	io_iterator_t	iter;
110	io_service_t 	fb;
111	io_name_t	name;
112	kern_return_t	kr;
113	void *		blitter;
114	int		quality, i;
115	int		color, x, y;
116	thread_port_t	tself;
117        volatile UInt64	start, end;
118	int		waited, busy;
119	boolean_t	didit;
120
121UInt32 * vars;
122IOGraphicsEngineContext * shmem;
123
124	if( reset) {
125	}
126	if( !count)
127		count = 10000;
128
129	assert( KERN_SUCCESS == (
130	kr = IOServiceGetMatchingServices( masterPort,
131			 IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO ), &iter)
132	));
133
134	assert(
135	fb = IOIteratorNext( iter )
136	);
137
138	assert( KERN_SUCCESS == (
139	kr = IORegistryEntryGetName( fb, name )
140	));
141
142	assert( KERN_SUCCESS == (
143	kr = IOPSAllocateBlitEngine( fb, &blitter, &quality )
144	));
145
146vars = (UInt32 *) blitter;
147shmem = (IOGraphicsEngineContext *) vars[ 3 ];
148srandom( shmem->reserved[0] );
149
150	tself = random();
151	x = tself % 600;
152	tself = random();
153	y = tself % 500;
154        shmem->reserved[0] = tself;
155
156	waited = busy = 0;
157
158        start = CFReadTSR();
159	for( i = 0; i < count; i++ ) {
160//	    IOPSBlitFill( blitter, x, y, 200, 200, color );
161	    IOPSBlitInvert( blitter, x, y, 100, 1 );
162	}
163	IOPSBlitIdle( blitter );
164
165        end = CFReadTSR();
166
167//        thread_switch( 0, SWITCH_OPTION_WAIT, 2 * 1000 );
168
169	printf("%s: Count: %d, ", name, count );
170	printElapsed( start, end );
171
172	IOObjectRelease( iter );
173	IOObjectRelease( fb );
174}
175
176
177void SetCursor( StdFBShmem_t * fbshmem);
178void SetCursor( StdFBShmem_t * fbshmem)
179{
180        UInt32 cursor[] = {
181            0x00004000,0x60007000,0x78007C00,0x7E007F00,
182            0x7F807C00,0x6C004600,0x06000300,0x03000000,
183            0xC000E000,0xF000F800,0xFC00FE00,0xFF00FF80,
184            0xFFC0FFE0,0xFE00EF00,0xCF008780,0x07800380,
185            0x00080001,
186        };
187        UInt32 * 	dataPtr;
188        UInt32   	data, mask;
189        volatile UInt8 *  dataOut;
190	int	 	i;
191
192        dataPtr = cursor;
193        dataOut = fbshmem->cursor.bw8.image[0];
194        for( i = 0; i < 8; i++) {
195            data = *dataPtr++;
196            for( mask = 0x80000000; mask; mask >>= 1)
197                *dataOut++ = (data & mask) ? 0xff : 0x00;
198        }
199        dataOut = fbshmem->cursor.bw8.mask[0];
200        for( i = 0; i < 8; i++) {
201            data = *dataPtr++;
202            for( mask = 0x80000000; mask; mask >>= 1)
203                *dataOut++ = (data & mask) ? 0xff : 0x00;
204        }
205        data = *dataPtr++;
206        fbshmem->hotSpot[0].x = data >> 16;
207        fbshmem->hotSpot[0].y = data & 0xffff;
208
209	fbshmem->cursorShow = 1;
210}
211
212void SetupFBandHID( void )
213{
214	register kern_return_t	kr;
215	mach_port_t		ev, fb, enumer, iter;
216	io_name_t		name;
217	vm_address_t		shmem, vram;
218	vm_size_t		shmemSize;
219	int			i,j;
220	IODisplayModeID		displayMode;
221        IOIndex			displayDepth;
222	IOFramebufferInformation fbInfo;
223	IOPixelEncoding		format;
224
225	assert( KERN_SUCCESS == (
226	kr = IOServiceGetMatchingServices( masterPort,
227			 IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO ), &iter)
228	));
229
230	assert(
231	enumer = IOIteratorNext( iter )
232	);
233
234	assert( KERN_SUCCESS == (
235	kr = IORegistryEntryGetName( enumer, name )
236	));
237
238	printf("Opening %s\n", name);
239
240	assert( KERN_SUCCESS == (
241            kr = IOServiceOpen( enumer,
242			mach_task_self(),
243			kIOFBServerConnectType,
244			&fb)
245
246	));
247
248	IOObjectRelease( enumer );
249	enumer = 0;
250	assert( KERN_SUCCESS == (
251	kr = IOConnectGetService( fb, &enumer )
252	));
253
254	assert( KERN_SUCCESS == (
255	kr = IORegistryEntryGetName( enumer, name )
256	));
257
258	printf("Opened %s\n", name);
259
260	IOObjectRelease( iter );
261	IOObjectRelease( enumer );
262
263	assert( KERN_SUCCESS == (
264	kr = IOFBCreateSharedCursor( fb,
265			kIOFBCurrentShmemVersion, 32, 32)
266	));
267//exit(0);
268
269	assert( KERN_SUCCESS == (
270	kr = IOFBGetFramebufferInformationForAperture( fb, 0, &fbInfo)
271	));
272
273	assert( KERN_SUCCESS == (
274	kr = IOFBGetCurrentDisplayModeAndDepth( fb,
275			&displayMode, &displayDepth)
276	));
277
278	assert( KERN_SUCCESS == (
279	kr = IOFBGetPixelFormat( fb, displayMode, displayDepth,
280		kIOFBSystemAperture, &format)
281	));
282
283	assert( KERN_SUCCESS == (
284	kr = IOMapMemory( fb, kIOFBCursorMemory, mach_task_self(),
285			&shmem, &shmemSize, TRUE)
286	));
287
288	fbshmem = (StdFBShmem_t *)shmem;
289
290//	assert( sizeof( StdFBShmem_t) == fbshmem->structSize );
291	SetCursor( fbshmem);
292
293	assert( KERN_SUCCESS == (
294	kr = IOMapMemory( fb, kIOFBSystemAperture, mach_task_self(),
295		&vram, &shmemSize, TRUE)
296	));
297
298	if( 0 ) {
299            printf("%ld x %ld", fbInfo.activeWidth, fbInfo.activeHeight);
300            printf(", \"%s\"", format);
301            printf(", mode %ld-%ld", displayMode, displayDepth);
302            printf(", fbshmem mapped @ %x", fbshmem);
303            printf(", vram mapped @ %x", vram);
304            printf(", hidshmem mapped @ %x\n", kr, evg );
305	}
306
307        if( 1 ) {
308            unsigned char * bits = (unsigned char *) vram;
309
310            bits += (fbInfo.activeWidth / 2)
311                    + fbInfo.bytesPerRow * (fbInfo.activeHeight / 2);
312            for( i=0; i < 128; i++) {
313                for( j=0; j < 128; j++)
314                    bits[j] = ((i << 1) & 0xf0) | (j >> 3);
315                bits += fbInfo.bytesPerRow;
316            }
317        }
318
319	if( 1 ) {
320            unsigned char data[ 768 ];
321            for( i=0; i<256; i++) {
322                data[ i ] = 255 - i;
323                data[ i+ 256 ] = 255 - i;
324                data[ i+ 512 ] = 255 - i;
325            }
326#if 0
327            assert( KERN_SUCCESS == (
328            kr = IOFBSetGamma( fb, 3, 256, 8, data )
329            ));
330#endif
331	}
332
333if(0)	{
334	vm_address_t 			vs = vram;
335	vm_size_t			vl;
336	vm_region_basic_info_data_t	vminfo;
337	mach_msg_type_number_t		len = VM_REGION_BASIC_INFO_COUNT;
338	mach_port_t			obj;
339
340	kr = vm_region( mach_task_self(),
341		&vs, &vl,
342		VM_REGION_BASIC_INFO,
343		(vm_region_info_t) &vminfo,
344		&len,
345		&obj );
346
347	printf("vm_region = %lx, start: %08x, len: %08x\n", kr, vs, vl );
348	}
349
350	assert( KERN_SUCCESS == (
351	kr = IOServiceGetMatchingServices( masterPort,
352			 IOServiceMatching( kIOHIDSystemClass ), &iter)
353	));
354
355	assert(
356	enumer = IOIteratorNext( iter )
357	);
358
359	assert( KERN_SUCCESS == (
360	kr = IORegistryEntryGetName( enumer, name )
361	));
362
363	printf("Opening %s\n", name);
364
365	assert( KERN_SUCCESS == (
366        kr = IOServiceOpen( enumer,
367			mach_task_self(),
368			kIOHIDServerConnectType,
369			&ev)
370	));
371
372	IOObjectRelease( iter );
373
374	assert( KERN_SUCCESS == (
375	kr = IOHIDCreateSharedMemory( ev, kIOHIDCurrentShmemVersion)
376	));
377
378	assert( KERN_SUCCESS == (
379	kr = IOHIDSetEventsEnable( ev, TRUE)
380	));
381
382	assert( KERN_SUCCESS == (
383	kr = IORegisterClient( ev, fb)
384	));
385
386	assert( KERN_SUCCESS == (
387	kr = IOHIDSetCursorEnable( ev, TRUE)
388	));
389
390	assert( KERN_SUCCESS == (
391	kr = IOMapMemory( ev, kIOHIDGlobalMemory, mach_task_self(),
392			&shmem, &shmemSize, TRUE)
393	));
394
395	evg = (EvGlobals *)
396		(shmem + ((EvOffsets *)shmem)->evGlobalsOffset);
397
398	assert( sizeof( EvGlobals) == evg->structSize );
399
400//        printf("=%d, IOSetNotificationPort\n", kr);
401//        kr = IOSetNotificationPort( ev, kIOHIDEventNotification,
402//		bootstrap_event_port);
403
404	assert( KERN_SUCCESS == (
405	kr = IORegistryDisposeEnumerator( enumer)
406	));
407
408	if( 1 ) {
409            printf("%ld x %ld", fbInfo.activeWidth, fbInfo.activeHeight);
410            printf(", \"%s\"", format);
411            printf(", mode %ld-%ld", displayMode, displayDepth);
412            printf(", fbshmem mapped @ %x", fbshmem);
413            printf(", vram mapped @ %x", vram);
414            printf(", hidshmem mapped @ %x\n", evg );
415	}
416}
417
418void dumpIter( io_iterator_t iter )
419{
420    kern_return_t	kr;
421    io_object_t		obj;
422    io_name_t		name;
423    io_string_t		path;
424
425    while( (obj = IOIteratorNext( iter))) {
426        assert( KERN_SUCCESS == (
427        kr = IORegistryEntryGetName( obj, name )
428        ));
429	printf("name:%s(%d)\n", name, obj);
430        kr = IORegistryEntryGetPath( obj, "IOService", path );
431	if( KERN_SUCCESS == kr)
432	    // if the object is detached, getPath is expected to fail
433            printf("path:%s\n", path);
434//	IOObjectRelease( obj );
435    }
436}
437
438void regTest( void )
439{
440    UInt64		start, end;
441    kern_return_t	kr;
442    io_registry_entry_t	entry, root;
443    io_iterator_t	iter;
444    io_name_t		name;
445
446    assert( (
447    root = IORegistryEntryFromPath( masterPort, kIODeviceTreePlane ":/" )
448    ));
449
450    assert( KERN_SUCCESS == (
451    kr = IORegistryEntryGetChildIterator( root, kIODeviceTreePlane, &iter )
452    ));
453
454    printf("TOT: ");
455    entry = root;
456    do {
457        assert( KERN_SUCCESS == (
458        kr = IORegistryEntryGetName( entry, name )
459        ));
460	printf("%s, ", name);
461	IOObjectRelease( entry );
462    } while( (entry = IOIteratorNext( iter)));
463    printf("\n");
464
465    IOObjectRelease( iter );
466
467    assert( KERN_SUCCESS == (
468    kr = IORegistryCreateIterator( masterPort, kIOServicePlane, TRUE, &iter )
469    ));
470
471    printf("All service: ");
472    start = CFReadTSR();
473    dumpIter( iter );
474    end = CFReadTSR();
475
476    printElapsed( start, end );
477
478    IOObjectRelease( iter );
479}
480
481int
482main(int argc, char **argv)
483{
484	kern_return_t		kr;
485	boolean_t		reset = 0;
486	int			count = 0;
487
488	/*
489	 * Get master device port
490	 */
491	assert( KERN_SUCCESS == (
492	kr = IOMasterPort(   bootstrap_port,
493			     &masterPort)
494	));
495
496//	getClockFrequency();
497//	regTest();
498
499	if( argc > 1) {
500            reset = (0 == strcmp("reset", argv[1]));
501	    if( !reset)
502		count = strtol( argv[1], 0, 10 );
503	}
504
505//  	AccelTests( reset, count );
506
507	SetupFBandHID();
508
509//	printf("Done, sleeping...\n"); thread_switch( 0, SWITCH_OPTION_WAIT, 10 * 1000 );
510	printf("Exit\n");
511
512}
513
514