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 tests -lIOKit -Wno-four-char-constants -fno-rtti -fno-exceptions -fcheck-new -fvtable-thunks
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#define OLDCONNECT      0
42#define TRAP 1
43
44#include <mach/clock_types.h>
45#include <IOKit/IOKitLib.h>
46#include <IOKit/hidsystem/IOHIDShared.h>
47//#include <dev/evio.h>
48#include <IOKit/graphics/IOFramebufferShared.h>
49
50#include <IOKit/graphics/IOGraphicsEngine.h>
51
52EvGlobals *     evg;
53StdFBShmem_t *  fbshmem;
54mach_port_t     masterPort;
55unsigned int    clock_freq;
56
57/*
58 */
59
60inline UInt64 CFReadTSR() {
61    union {
62        UInt64 time64;
63        UInt32 word[2];
64    } now;
65
66    /* Read from PowerPC 64-bit time base register. The increment */
67    /* rate of the time base is implementation-dependent, but is */
68    /* 1/4th the bus clock cycle on 603/604/750 processors. */
69    UInt32 t3;
70    do {
71        __asm__ volatile("mftbu %0" : "=r" (now.word[0]));
72        __asm__ volatile("mftb %0" : "=r" (now.word[1]));
73        __asm__ volatile("mftbu %0" : "=r" (t3));
74    } while (now.word[0] != t3);
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 *          blitterRef;
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, &blitterRef, &quality )
144        ));
145
146#if 0
147vars = (UInt32 *) blitter;
148shmem = (IOGraphicsEngineContext *) vars[ 3 ];
149srandom( shmem->reserved[0] );
150
151        tself = random();
152        x = tself % 600;
153        tself = random();
154        y = tself % 500;
155        shmem->reserved[0] = tself;
156
157        waited = busy = 0;
158
159        start = CFReadTSR();
160        for( i = 0; i < count; i++ ) {
161//          IOPSBlitFill( blitter, x, y, 200, 200, color );
162            IOPSBlitInvert( blitter, x, y, 100, 1 );
163        }
164        IOPSBlitIdle( blitter );
165
166        end = CFReadTSR();
167
168//        thread_switch( 0, SWITCH_OPTION_WAIT, 2 * 1000 );
169
170        printf("%s: Count: %d, ", name, count );
171        printElapsed( start, end );
172#endif
173
174    if( 1 ) {
175
176        void *  burstRef;
177        int     count;
178        int     i,j = 0, lines;
179        UInt64  start,end;
180        int     w = 1280;
181        int     h = 100;
182        int     bytesPerPixel = 2;
183        int     slice = 1;
184        int     NUMBLITS = 300;
185        void *  fill1;
186        void *  fill2;
187
188        count = ((slice * h * bytesPerPixel) + 31) / 32;
189        fill1 = (void *)0x3c0001e0;
190        fill2 = (void *)0x3c0001e0;
191
192        start = CFReadTSR();
193
194        for( i=0; i < NUMBLITS; i++) {
195            for( j=0; j < w; j += slice) {
196                assert( KERN_SUCCESS == (
197                    kr = IOFBSetupFIFOBurst( blitterRef, j, 200, slice, h, 0,
198                                                &burstRef )
199                ));
200                lines = count;
201                while( lines--)
202                    IOFBBurstWrite32( fill1, fill2, fill1, fill2,
203                                        fill1, fill2, fill1, fill2 );
204           }
205        }
206
207        end = CFReadTSR();
208
209        {
210        double bytes = w * h * 2 * NUMBLITS;
211        double secs = (end - start);
212
213        secs /= 24932500;
214
215        printf("%d x %d * %d = %qd ticks\n", w, h, NUMBLITS, end - start);
216        printf("%f bytes %f secs, %f Mbytes per sec\n", bytes, secs,
217                        bytes / secs / 1024 / 1024);
218        }
219    }
220
221        IOObjectRelease( iter );
222        IOObjectRelease( fb );
223}
224
225
226void SetCursor( StdFBShmem_t * fbshmem);
227void SetCursor( StdFBShmem_t * fbshmem)
228{
229        UInt32 cursor[] = {
230            0x00004000,0x60007000,0x78007C00,0x7E007F00,
231            0x7F807C00,0x6C004600,0x06000300,0x03000000,
232            0xC000E000,0xF000F800,0xFC00FE00,0xFF00FF80,
233            0xFFC0FFE0,0xFE00EF00,0xCF008780,0x07800380,
234            0x00080001,
235        };
236        UInt32 *        dataPtr;
237        UInt32          data, mask;
238        volatile UInt8 *  dataOut;
239        int             i;
240
241        dataPtr = cursor;
242        dataOut = fbshmem->cursor.bw8.image[0];
243        for( i = 0; i < 8; i++) {
244            data = *dataPtr++;
245            for( mask = 0x80000000; mask; mask >>= 1)
246                *dataOut++ = (data & mask) ? 0xff : 0x00;
247        }
248        dataOut = fbshmem->cursor.bw8.mask[0];
249        for( i = 0; i < 8; i++) {
250            data = *dataPtr++;
251            for( mask = 0x80000000; mask; mask >>= 1)
252                *dataOut++ = (data & mask) ? 0xff : 0x00;
253        }
254        data = *dataPtr++;
255        fbshmem->hotSpot[0].x = data >> 16;
256        fbshmem->hotSpot[0].y = data & 0xffff;
257
258        fbshmem->cursorShow = 1;
259}
260
261
262
263void SetupFBandHID( void )
264{
265        register kern_return_t  kr;
266        mach_port_t             ev, fb, enumer, iter;
267        io_name_t               name;
268        vm_address_t            shmem, vram;
269        vm_size_t               shmemSize;
270        int                     i,j;
271        IODisplayModeID         displayMode;
272        IOIndex                 displayDepth;
273        IOFramebufferInformation fbInfo;
274        IOPixelEncoding         format;
275
276#if OLDCONNECT
277
278        assert( KERN_SUCCESS == (
279        kr = IORegistryCreateEnumerator( masterPort,
280                         &enumer)
281        ));
282
283        assert( KERN_SUCCESS == (
284        kr = IORegistryEnumeratorNextConforming( enumer,
285                         (char *) IOFRAMEBUFFER_CONFORMSTO, TRUE)
286        ));
287
288        assert( KERN_SUCCESS == (
289        kr = IOOpenConnection( enumer,
290                        mach_task_self(),
291                        kIOFBServerConnectType,
292                        &fb)
293        ));
294
295#else
296        assert( KERN_SUCCESS == (
297        kr = IOServiceGetMatchingServices( masterPort,
298                         IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO ), &iter)
299        ));
300
301        assert(
302        enumer = IOIteratorNext( iter )
303        );
304
305        assert( KERN_SUCCESS == (
306        kr = IORegistryEntryGetName( enumer, name )
307        ));
308
309        printf("Opening %s\n", name);
310
311        assert( KERN_SUCCESS == (
312            kr = IOServiceOpen( enumer,
313                        mach_task_self(),
314                        kIOFBServerConnectType,
315                        &fb)
316
317        ));
318
319        IOObjectRelease( enumer );
320        enumer = 0;
321        assert( KERN_SUCCESS == (
322        kr = IOConnectGetService( fb, &enumer )
323        ));
324
325        assert( KERN_SUCCESS == (
326        kr = IORegistryEntryGetName( enumer, name )
327        ));
328
329        printf("Opened %s\n", name);
330
331        IOObjectRelease( iter );
332        IOObjectRelease( enumer );
333#endif
334
335        assert( KERN_SUCCESS == (
336        kr = IOFBCreateSharedCursor( fb,
337                        kIOFBCurrentShmemVersion, 32, 32)
338        ));
339//exit(0);
340
341        assert( KERN_SUCCESS == (
342        kr = IOFBGetFramebufferInformationForAperture( fb, 0, &fbInfo)
343        ));
344
345        assert( KERN_SUCCESS == (
346        kr = IOFBGetCurrentDisplayModeAndDepth( fb,
347                        &displayMode, &displayDepth)
348        ));
349
350        assert( KERN_SUCCESS == (
351        kr = IOFBGetPixelFormat( fb, displayMode, displayDepth,
352                kIOFBSystemAperture, &format)
353        ));
354
355        assert( KERN_SUCCESS == (
356        kr = IOMapMemory( fb, kIOFBCursorMemory, mach_task_self(),
357                        &shmem, &shmemSize, TRUE)
358        ));
359
360        fbshmem = (StdFBShmem_t *)shmem;
361
362//      assert( sizeof( StdFBShmem_t) == fbshmem->structSize );
363        SetCursor( fbshmem);
364
365        assert( KERN_SUCCESS == (
366        kr = IOConnectMapMemory( fb, kIOFBSystemAperture, mach_task_self(),
367                &vram, &shmemSize, kIOMapDefaultCache | kIOMapAnywhere)
368        ));
369
370        assert( KERN_SUCCESS == (
371        kr = IOConnectMapMemory( fb, kIOFBSystemAperture, mach_task_self(),
372                &vram, &shmemSize, kIOMapCopybackCache | kIOMapAnywhere)
373        ));
374
375        if( 0 ) {
376            printf("%ld x %ld", fbInfo.activeWidth, fbInfo.activeHeight);
377            printf(", \"%s\"", format);
378            printf(", mode %ld-%ld", displayMode, displayDepth);
379            printf(", fbshmem mapped @ %x", fbshmem);
380            printf(", vram mapped @ %x", vram);
381            printf(", hidshmem mapped @ %x\n", kr, evg );
382        }
383
384        if( 1 ) {
385            unsigned char * bits = (unsigned char *) vram;
386
387            bits += (fbInfo.activeWidth / 2)
388                    + fbInfo.bytesPerRow * (fbInfo.activeHeight / 2);
389            for( i=0; i < 128; i++) {
390                for( j=0; j < 128; j++)
391                    bits[j] = ((i << 1) & 0xf0) | (j >> 3);
392                bits += fbInfo.bytesPerRow;
393            }
394        }
395
396        if( 0 ) {
397            unsigned char data[ 768 ];
398            for( i=0; i<256; i++) {
399                data[ i ] = 255 - i;
400                data[ i+ 256 ] = 255 - i;
401                data[ i+ 512 ] = 255 - i;
402            }
403            assert( KERN_SUCCESS == (
404            kr = IOFBSetGamma( fb, 3, 256, 8, data )
405            ));
406        }
407
408if(0)   {
409        vm_address_t                    vs = vram;
410        vm_size_t                       vl;
411        vm_region_basic_info_data_t     vminfo;
412        mach_msg_type_number_t          len = VM_REGION_BASIC_INFO_COUNT;
413        mach_port_t                     obj;
414
415        kr = vm_region( mach_task_self(),
416                &vs, &vl,
417                VM_REGION_BASIC_INFO,
418                (vm_region_info_t) &vminfo,
419                &len,
420                &obj );
421
422        printf("vm_region = %lx, start: %08x, len: %08x\n", kr, vs, vl );
423        }
424
425#if OLDCONNECT
426        assert( KERN_SUCCESS == (
427        kr = IORegistryEnumeratorReset( enumer)
428        ));
429
430        assert( KERN_SUCCESS == (
431        kr = IORegistryEnumeratorNextConforming( enumer,
432                         (char *) kIOHIDSystemClass, TRUE)
433        ));
434
435        assert( KERN_SUCCESS == (
436        kr = IOOpenConnection( enumer,
437                        mach_task_self(),
438                        kIOFBServerConnectType,
439                        &ev)
440        ));
441#else
442        assert( KERN_SUCCESS == (
443        kr = IOServiceGetMatchingServices( masterPort,
444                         IOServiceMatching( kIOHIDSystemClass ), &iter)
445        ));
446
447        assert(
448        enumer = IOIteratorNext( iter )
449        );
450
451        assert( KERN_SUCCESS == (
452        kr = IORegistryEntryGetName( enumer, name )
453        ));
454
455        printf("Opening %s\n", name);
456
457        assert( KERN_SUCCESS == (
458        kr = IOServiceOpen( enumer,
459                        mach_task_self(),
460                        kIOHIDServerConnectType,
461                        &ev)
462        ));
463
464        IOObjectRelease( iter );
465#endif
466
467        assert( KERN_SUCCESS == (
468        kr = IOHIDCreateSharedMemory( ev, kIOHIDCurrentShmemVersion)
469        ));
470
471        assert( KERN_SUCCESS == (
472        kr = IOHIDSetEventsEnable( ev, TRUE)
473        ));
474
475        assert( KERN_SUCCESS == (
476        kr = IORegisterClient( ev, fb)
477        ));
478
479        assert( KERN_SUCCESS == (
480        kr = IOHIDSetCursorEnable( ev, TRUE)
481        ));
482
483        assert( KERN_SUCCESS == (
484        kr = IOMapMemory( ev, kIOHIDGlobalMemory, mach_task_self(),
485                        &shmem, &shmemSize, TRUE)
486        ));
487
488        evg = (EvGlobals *)
489                (shmem + ((EvOffsets *)shmem)->evGlobalsOffset);
490
491        assert( sizeof( EvGlobals) == evg->structSize );
492
493//        printf("=%d, IOSetNotificationPort\n", kr);
494//        kr = IOSetNotificationPort( ev, kIOHIDEventNotification,
495//              bootstrap_event_port);
496
497        assert( KERN_SUCCESS == (
498        kr = IORegistryDisposeEnumerator( enumer)
499        ));
500
501        if( 1 ) {
502            printf("%ld x %ld", fbInfo.activeWidth, fbInfo.activeHeight);
503            printf(", \"%s\"", format);
504            printf(", mode %ld-%ld", displayMode, displayDepth);
505            printf(", fbshmem mapped @ %x", fbshmem);
506            printf(", vram mapped @ %x", vram);
507            printf(", hidshmem mapped @ %x\n", kr, evg );
508        }
509}
510
511void dumpIter( io_iterator_t iter )
512{
513    kern_return_t       kr;
514    io_object_t         obj;
515    io_name_t           name;
516    io_string_t         path;
517
518    while( (obj = IOIteratorNext( iter))) {
519        assert( KERN_SUCCESS == (
520        kr = IORegistryEntryGetName( obj, name )
521        ));
522        printf("name:%s(%d)\n", name, obj);
523        kr = IORegistryEntryGetPath( obj, "IOService", path );
524        if( KERN_SUCCESS == kr)
525            // if the object is detached, getPath is expected to fail
526            printf("path:%s\n", path);
527//      IOObjectRelease( obj );
528    }
529}
530
531void regTest( void )
532{
533    UInt64              start, end;
534    kern_return_t       kr;
535    io_registry_entry_t entry, root;
536    io_iterator_t       iter;
537    io_name_t           name;
538
539    assert( (
540    root = IORegistryEntryFromPath( masterPort, kIODeviceTreePlane ":/" )
541    ));
542
543    assert( KERN_SUCCESS == (
544    kr = IORegistryEntryGetChildIterator( root, kIODeviceTreePlane, &iter )
545    ));
546
547    printf("TOT: ");
548    entry = root;
549    do {
550        assert( KERN_SUCCESS == (
551        kr = IORegistryEntryGetName( entry, name )
552        ));
553        printf("%s, ", name);
554        IOObjectRelease( entry );
555    } while( (entry = IOIteratorNext( iter)));
556    printf("\n");
557
558    IOObjectRelease( iter );
559
560    assert( KERN_SUCCESS == (
561    kr = IORegistryCreateIterator( masterPort, kIOServicePlane, TRUE, &iter )
562    ));
563
564    printf("All service: ");
565    start = CFReadTSR();
566    dumpIter( iter );
567    end = CFReadTSR();
568
569    printElapsed( start, end );
570
571    IOObjectRelease( iter );
572}
573
574int
575main(int argc, char **argv)
576{
577        kern_return_t           kr;
578        boolean_t               reset = 0;
579        int                     count = 0;
580
581        /*
582         * Get master device port
583         */
584        assert( KERN_SUCCESS == (
585        kr = IOMasterPort(   bootstrap_port,
586                             &masterPort)
587        ));
588
589//      getClockFrequency();
590//      regTest();
591
592        if( argc > 1) {
593            reset = (0 == strcmp("reset", argv[1]));
594            if( !reset)
595                count = strtol( argv[1], 0, 10 );
596        }
597
598        AccelTests( reset, count );
599
600//      SetupFBandHID();
601
602//      printf("Done, sleeping...\n"); thread_switch( 0, SWITCH_OPTION_WAIT, 10 * 1000 );
603        printf("Exit\n");
604
605}
606
607