Annotation of driverkit/libDriver/Kernel/EventDriver.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*     Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved. 
                     25:  *
                     26:  * EventDriver.m - Event System module, ObjC implementation.
                     27:  *
                     28:  *             The EventDriver is a pseudo-device driver.
                     29:  *
                     30:  * HISTORY
                     31:  * 31-Mar-92    Mike Paquette at NeXT 
                     32:  *      Created. 
                     33:  * 4  Aug 1993   Erik Kay at NeXT
                     34:  *     minor API cleanup
                     35:  */
                     36: 
                     37: #import <driverkit/generalFuncs.h>
                     38: #import <machkit/NXLock.h>
                     39: #import <driverkit/Device_ddm.h>
                     40: #import <driverkit/kernelDriver.h>
                     41: #import <mach/notify.h>
                     42: #import <bsd/dev/evio.h>
                     43: #import <kern/queue.h>
                     44: #import <bsd/dev/machine/ev_private.h> /* Per-machine configuration info */
                     45: #import <driverkit/EventDriver.h>
                     46: #import <driverkit/EventInput.h>
                     47: #import <bsd/dev/evsio.h>
                     48: 
                     49: #define EVSRC_PRINT    0
                     50: #if    EVSRC_PRINT
                     51: #undef xpr_evsrc
                     52: #define xpr_evsrc(x,a,b,c,d,e) printf(x,a,b,c,d,e)
                     53: #endif EVSRC_PRINT
                     54: 
                     55: static EventDriver *evInstance = (EventDriver *)nil;
                     56: static volatile void EventListener(EventDriver *inst);
                     57: 
                     58: typedef void * kern_port_t;
                     59: #define KERN_PORT_NULL ((kern_port_t) 0)
                     60: 
                     61: /*
                     62:  * Template for evIoOpMsg.
                     63:  */
                     64: static evIoOpMsg opMsgTemplate = {
                     65: 
                     66:         {                                              // header 
                     67:                 0,                                     // msg_unused 
                     68:                 1,                                     // msg_simple 
                     69:                 sizeof(evIoOpMsg),                     // msg_size 
                     70:                 MSG_TYPE_NORMAL,                       // msg_type 
                     71:                 PORT_NULL,                             // msg_local_port 
                     72:                 PORT_NULL,                             // msg_remote_port - TO
                     73:                                                         // BE FILLED IN 
                     74:                 (int)EV_IO_OP_MSG_ID                   // msg_id 
                     75:         },
                     76:         {                                              // type 
                     77:                 MSG_TYPE_UNSTRUCTURED,                 // msg_type_name 
                     78:                 sizeof(evIoOpBuf) * 8,                 // msg_type_size 
                     79:                 1,                                     // msg_type_number 
                     80:                 1,                                     // msg_type_inline 
                     81:                 0,                                     // msg_type_longform 
                     82:                 0,                                     // msg_type_deallocate 
                     83:                 0                                      // msg_type_unused
                     84:         },
                     85:         { 0 }                                          /* evIoOpBuf - TO BE 
                     86:                                                         * FILLED IN */
                     87: };
                     88: 
                     89: static void nsecs_to_packed_ns(ns_time_t *nsecs, unsigned int *pnsecs)
                     90: {
                     91:        _NX_packed_time_t data;
                     92:        int i;
                     93: 
                     94:        data.tval = *nsecs;     // nsecs to ns_time_t
                     95:        for ( i = 0; i < EVS_PACKED_TIME_SIZE; ++i )
                     96:                pnsecs[i] = data.itval[i];
                     97: }
                     98: 
                     99: static void packed_nsecs_to_nsecs(unsigned int *pnsecs, ns_time_t *nsecs)
                    100: {
                    101:        _NX_packed_time_t data;
                    102:        int i;
                    103: 
                    104:        for ( i = 0; i < EVS_PACKED_TIME_SIZE; ++i )
                    105:                data.itval[i] = pnsecs[i];
                    106:        *nsecs = data.tval;
                    107: }
                    108: 
                    109: @implementation EventDriver: IODevice
                    110: 
                    111: /* Probe routine for a pseudo-device driver. */
                    112: + (BOOL)probe : deviceDescription
                    113: {      
                    114:        if ( evInstance != nil )
                    115:                return YES;
                    116: 
                    117:        evInstance = [self alloc];
                    118:        /*
                    119:         * Take care of private stuff...
                    120:         */
                    121:        evInstance->devicePort = PORT_NULL;
                    122:        [evInstance setUnit:0];
                    123:        [evInstance setName:"event0"];
                    124:        [evInstance setDeviceKind:"event"];
                    125:        
                    126:        return ([evInstance init] ? YES : NO);
                    127: }
                    128: 
                    129: + (IODeviceStyle)deviceStyle
                    130: {
                    131:        return IO_PseudoDevice;
                    132: }
                    133: 
                    134: /* subclass specific methods */
                    135: 
                    136: /* Return the current instance of the EventDriver, or nil if none. */
                    137: + instance
                    138: {
                    139:        return (id)evInstance;
                    140: }
                    141: 
                    142: /*
                    143:  * Perform reusable initialization actions here.
                    144:  */
                    145: - init
                    146: {
                    147:        kern_return_t krtn;
                    148:        IOReturn drtn;
                    149:        IOThread thread;
                    150: #ifdef KERNEL
                    151:        extern kern_port_t ev_port_list[];
                    152: #endif
                    153:        
                    154:        driverLock = [NXLock new];      // Event driver data protection lock
                    155:        eventSrcListLock = [NXLock new];
                    156:        kickConsumerLock = [NXLock new];
                    157: 
                    158:        /*
                    159:         * Set up the ports we'll be using.
                    160:         */
                    161:        krtn = port_allocate(task_self(), &ev_port);
                    162:        if(krtn) {
                    163:                xpr_err("Ev init: port_allocate returned %d\n", krtn, 2,3,4,5);
                    164:                return nil;
                    165:        }
                    166: 
                    167:        krtn = port_allocate(task_self(), &evs_port);
                    168:        if(krtn) {
                    169:                xpr_err("Ev init: port_allocate returned %d\n", krtn, 2,3,4,5);
                    170:                return nil;
                    171:        }
                    172:        krtn = port_allocate(task_self(), &notify_port);
                    173:        if(krtn) {
                    174:                xpr_err("Ev init: port_allocate returned %d\n", krtn, 2,3,4,5);
                    175:                return nil;
                    176:        }
                    177: #ifdef KERNEL
                    178:        /*
                    179:         * Get a kern_port_t version of same for use with 
                    180:         * msg_send_from_kernel().
                    181:         */
                    182:        ev_port_list[0] = (kern_port_t)IOGetKernPort(ev_port);
                    183:        ev_port_list[1] = (kern_port_t)IOGetKernPort(evs_port);
                    184:        notify_kern_port = IOGetKernPort(notify_port);
                    185: #endif KERNEL
                    186:        krtn = port_set_allocate(task_self(), &ev_port_set);
                    187:        if(krtn) {
                    188:                xpr_err("adbInit: port_set_allocate returned %d\n", 
                    189:                        krtn, 2,3,4,5);
                    190:                return nil;
                    191:        }
                    192:        krtn = port_set_add(task_self(), ev_port_set, ev_port);
                    193:        if(krtn) {
                    194:                xpr_err("Ev init: port_set_add returned %d\n", krtn, 2,3,4,5);
                    195:                return nil;
                    196:        }
                    197:        krtn = port_set_add(task_self(), ev_port_set, evs_port);
                    198:        if(krtn) {
                    199:                xpr_err("Ev init: port_set_add returned %d\n", krtn, 2,3,4,5);
                    200:                return nil;
                    201:        }
                    202:        krtn = port_set_add(task_self(), ev_port_set, notify_port);
                    203:        if(krtn) {
                    204:                xpr_err("Ev init: port_set_add returned %d\n", krtn, 2,3,4,5);
                    205:                return nil;
                    206:        }
                    207:        
                    208:        /*
                    209:         * Initialize the eventSrc list.
                    210:         */
                    211:        queue_init(&eventSrcList);
                    212: 
                    213:        /*
                    214:         * Have IODevice do its thing.
                    215:         */
                    216:        [super init];
                    217: 
                    218:        /* A few details to be set up... */
                    219:        pointerLoc.x = INIT_CURSOR_X;
                    220:        pointerLoc.y = INIT_CURSOR_Y;
                    221: 
                    222:        /*
                    223:         * Start up the I/O thread and wait for it to finish 
                    224:         * initialization via an AIO_PING command.
                    225:         */
                    226:        thread = IOForkThread((IOThreadFunc)EventListener, self);
                    227:        (void) IOSetThreadPolicy(thread, POLICY_FIXEDPRI);
                    228:        (void) IOSetThreadPriority(thread, 28); /* XXX */
                    229: 
                    230:        if ( ! hasRegistered )
                    231:        {
                    232:                [self registerDevice];
                    233:                hasRegistered = YES;
                    234:        }
                    235:        return self;
                    236: }
                    237: 
                    238: /*
                    239:  * Free locally allocated resources, and then ourselves.
                    240:  */
                    241: - free
                    242: {
                    243:        /* Initiates a normal close if open */
                    244:        [self evClose:ev_port token:eventPort];
                    245: 
                    246:        /*
                    247:         * Destroy the ports and port set listenerThread is using.
                    248:         * This will cause it to return from msg_receive() with an
                    249:         * error.  It should take this as a clue to exit.
                    250:         */
                    251:        port_deallocate(task_self(), ev_port);
                    252:        port_deallocate(task_self(), evs_port);
                    253:        port_deallocate(task_self(), notify_port);
                    254:        port_set_deallocate(task_self(), ev_port_set);
                    255: 
                    256:        /* Release locally allocated resources */
                    257:        [eventSrcListLock free];
                    258:        [driverLock free];
                    259:        return [super free];
                    260: }
                    261: 
                    262: /*
                    263:  * Open the driver for business.  This call must be made before
                    264:  * any other calls to the Event driver.  We can only be opened by
                    265:  * one user at a time.
                    266:  */
                    267: - (IOReturn)evOpen:(port_t)dev_port token:(port_t)event_port
                    268: {
                    269:        IOReturn r = IO_R_SUCCESS;
                    270: 
                    271:        if ( dev_port != ev_port )
                    272:                return IO_R_INVALID_ARG;
                    273: 
                    274:        [driverLock lock];
                    275:        
                    276:        if ( evOpenCalled == YES )
                    277:        {
                    278:                r = IO_R_BUSY;
                    279:                goto done;
                    280:        }
                    281:        evOpenCalled = YES;
                    282: 
                    283:        if (!evInitialized)
                    284:        {
                    285:            evInitialized = YES;
                    286:            curBright = EV_SCREEN_MAX_BRIGHTNESS; // FIXME: Set from NVRAM?
                    287:            curVolume = EV_AUDIO_MAX_VOLUME / 2; // FIXME: Set from NVRAM?
                    288:            // Put code here that is to run on the first open ONLY.
                    289:        }
                    290: 
                    291:        [self setEventPort:event_port];
                    292:        // Init local state
                    293:        // IODDMMasks[XPR_EVENTDRIVER_INDEX] |= XPR_EVSRC;
                    294:        // IODDMMasks[XPR_IODEVICE_INDEX] |= XPR_ADB;
                    295: done:
                    296:        [driverLock unlock];
                    297:        return r;
                    298: }
                    299: 
                    300: - (IOReturn)evClose:(port_t)dev_port token:(port_t)event_port
                    301: {
                    302:        [driverLock lock];
                    303:        if ( evOpenCalled == NO || event_port != eventPort )
                    304:        {
                    305:                [driverLock unlock];
                    306:                return IO_R_INVALID_ARG;
                    307:        }
                    308:        // Early close actions here
                    309:        [self forceAutoDimState:NO];
                    310:        [self hideCursor];
                    311: 
                    312:        [driverLock unlock];
                    313: 
                    314:        // Release the input devices.
                    315:        [self detachEventSources];
                    316: 
                    317:        // Tear down the shared memory area if set up
                    318:        if ( eventsOpen == YES )
                    319:            [self unmapEventShmem:eventPort];
                    320: 
                    321:        [driverLock lock];
                    322:        // Clear screens registry and related data
                    323:        if ( evScreen != (void *)0 )
                    324:        {
                    325:            IOFree( (void *)evScreen, evScreenSize );
                    326:            evScreen = (void *)0;
                    327:            evScreenSize = 0;
                    328:            screens = 0;
                    329:            lastShmemPtr = (void *)0;
                    330:        }
                    331:        // Remove port notification for the eventPort and clear the port out
                    332:        [self setEventPort:PORT_NULL];
                    333: 
                    334:        // Clear local state to shutdown
                    335:        evOpenCalled = NO;
                    336:        [driverLock unlock];
                    337: 
                    338:        return IO_R_SUCCESS;
                    339: }
                    340: 
                    341: - (IOReturn)evFrameBufferDevicePort:(port_t)event_port
                    342:                  unitName:(IOString)name
                    343:                  unitClass:(IOString)class
                    344:                  unitPort:(port_t *)port
                    345: {
                    346:        id instance;
                    347:        IOReturn r;
                    348: 
                    349:        *port = PORT_NULL;
                    350:        if ( evOpenCalled == NO || event_port != eventPort )
                    351:                return IO_R_INVALID_ARG;
                    352: 
                    353:        if ( (r = IOGetObjectForDeviceName( name, &instance )) != IO_R_SUCCESS )
                    354:        {       // Not checked in yet.  Lookup class and force a probe
                    355:                if ( (instance = objc_getClass(class)) == nil )
                    356:                    return r;
                    357:                if ( [instance respondsTo:@selector(probe)] == NO )
                    358:                    return r;
                    359:                if ( (instance = [instance probe]) == nil )
                    360:                    return r;
                    361:        }
                    362: 
                    363:        if ( [instance respondsTo:@selector(devicePort)] == NO )
                    364:                return IO_R_PRIVILEGE;
                    365: 
                    366:        *port = [instance devicePort];
                    367:        return IO_R_SUCCESS;
                    368: }
                    369: 
                    370: /*
                    371:  * General get/set parameter methods for use with the
                    372:  * event system.  These replace the old evs ioctl calls.
                    373:  *
                    374:  *     We could wind up not needing any of these, in which case we should
                    375:  *     toss them out and let inheritance take care of the messages.
                    376:  */
                    377: - (IOReturn)getIntValues               : (unsigned *)parameterArray
                    378:                           forParameter : (IOParameterName)parameterName
                    379:                                  count : (unsigned *)count;    // in/out
                    380: {
                    381:        IOReturn r = IO_R_INVALID_ARG;
                    382:        IOReturn retval;
                    383:        attachedEventSrc *device;
                    384:        id      srcInstance;
                    385:        ns_time_t       nst;
                    386:        unsigned        maxCount = *count;
                    387:        unsigned        returnedCount = 0;
                    388:        
                    389:        // Report the ID for the last left/right button down event
                    390:        if (   strcmp( parameterName, EVIOEVNUM ) == 0 )
                    391:        {
                    392:            if ( maxCount >= EVIOEVNUM_SIZE )
                    393:            {
                    394:                returnedCount = EVIOEVNUM_SIZE;
                    395:                [driverLock lock];
                    396:                parameterArray[EVIOEVNUM_LEFT] = leftENum;
                    397:                parameterArray[EVIOEVNUM_RIGHT] = rightENum;
                    398:                [driverLock unlock];
                    399:                r = IO_R_SUCCESS;
                    400:            }
                    401:        }
                    402:        else if ( strcmp( parameterName, EVIOSHMEMSIZE ) == 0 )
                    403:        {
                    404:            if ( maxCount >= EVIOSHMEMSIZE_SIZE )
                    405:            {
                    406:                returnedCount = EVIOSHMEMSIZE_SIZE;
                    407:                parameterArray[0] = shmem_size;
                    408:                r = IO_R_SUCCESS;
                    409:            }
                    410:        }
                    411:        else if (   strcmp( parameterName, EVSIOCWINFO ) == 0 )
                    412:        {
                    413:            if ( maxCount >= EVSIOCWINFO_SIZE )
                    414:            {
                    415:                returnedCount = EVSIOCWINFO_SIZE;
                    416:                [driverLock lock];
                    417:                if ( eventsOpen == YES )
                    418:                    nst = EV_TICK_TO_NS(((EvGlobals*)evg)->waitThreshold);
                    419:                else
                    420:                    nst = 0ULL;
                    421:                nsecs_to_packed_ns(&nst,&parameterArray[EVSIOCWINFO_THRESH]);
                    422:                nsecs_to_packed_ns(&waitSustain,
                    423:                                &parameterArray[EVSIOCWINFO_SUSTAIN]);
                    424:                nsecs_to_packed_ns(&waitFrameRate,
                    425:                                &parameterArray[EVSIOCWINFO_FINTERVAL]);
                    426:                [driverLock unlock];
                    427:                r = IO_R_SUCCESS;
                    428:            }
                    429:        }
                    430:        else if (   strcmp( parameterName, EVSIO_DCTLINFO ) == 0 )
                    431:        {
                    432:            if ( maxCount >= EVSIO_DCTLINFO_SIZE )
                    433:            {
                    434:                returnedCount = EVSIO_DCTLINFO_SIZE;
                    435:                [driverLock lock];
                    436:                parameterArray[EVSIO_DCTLINFO_BRIGHT] =
                    437:                        [self brightness];
                    438:                // EVSIO_DCTLINFO_ATTEN obsolete once libc-67 is released
                    439:                parameterArray[EVSIO_DCTLINFO_ATTEN] = curVolume;
                    440:                parameterArray[EVSIO_DCTLINFO_AUTODIMBRIGHT] =
                    441:                        [self autoDimBrightness];
                    442:                [driverLock unlock];
                    443:                r = IO_R_SUCCESS;
                    444:            }
                    445:        }
                    446:        else if (   strcmp( parameterName, EVSIOCCT ) == 0 )
                    447:        {
                    448:            if ( maxCount >= EVSIOCCT_SIZE )
                    449:            {
                    450:                returnedCount = EVSIOCCT_SIZE;
                    451:                [driverLock lock];
                    452:                nst = EV_TICK_TO_NS(clickTimeThresh);
                    453:                nsecs_to_packed_ns(&nst,&parameterArray[0]);
                    454:                [driverLock unlock];
                    455:                r = IO_R_SUCCESS;
                    456:            }
                    457:        }
                    458:        else if (   strcmp( parameterName, EVSIOCADT ) == 0 )
                    459:        {
                    460:            if ( maxCount >= EVSIOCADT_SIZE )
                    461:            {
                    462:                returnedCount = EVSIOCADT_SIZE;
                    463:                [driverLock lock];
                    464:                nst = EV_TICK_TO_NS(autoDimPeriod);
                    465:                nsecs_to_packed_ns(&nst,&parameterArray[0]);
                    466:                [driverLock unlock];
                    467:                r = IO_R_SUCCESS;
                    468:            }
                    469:        }
                    470:        else if (   strcmp( parameterName, EVSIOGDADT ) == 0 )
                    471:        {
                    472:            if ( maxCount >= EVSIOGDADT_SIZE )
                    473:            {
                    474:                returnedCount = EVSIOGDADT_SIZE;
                    475:                [driverLock lock];
                    476:                if ( eventsOpen == YES )
                    477:                {
                    478:                    if ( autoDimmed )
                    479:                        nst = EV_TICK_TO_NS(0);
                    480:                    else
                    481:                        nst = EV_TICK_TO_NS(autoDimTime -
                    482:                                        ((EvGlobals*)evg)->VertRetraceClock);
                    483:                }
                    484:                else
                    485:                    nst = EV_TICK_TO_NS(autoDimPeriod);
                    486:                nsecs_to_packed_ns(&nst,&parameterArray[0]);
                    487:                [driverLock unlock];
                    488:                r = IO_R_SUCCESS;
                    489:            }
                    490:        }
                    491:        // added april 7, 1994 EK - to fix bug 41768
                    492:        else if (   strcmp( parameterName, EVSIOIDLE ) == 0 )
                    493:        {
                    494:            if (maxCount >= EVSIOIDLE_SIZE)
                    495:            {
                    496:                returnedCount = EVSIOIDLE_SIZE;
                    497:                [driverLock lock];
                    498:                if (eventsOpen == YES)
                    499:                {
                    500:                    if (autoDimmed)
                    501:                        nst = EV_TICK_TO_NS(((EvGlobals*)evg)->VertRetraceClock 
                    502:                                        - (autoDimTime - autoDimPeriod));
                    503:                    else
                    504:                        nst = EV_TICK_TO_NS(autoDimPeriod - (autoDimTime -
                    505:                                        ((EvGlobals*)evg)->VertRetraceClock));
                    506:                }
                    507:                else
                    508:                    nst = EV_TICK_TO_NS(0); // user is active
                    509:                nsecs_to_packed_ns(&nst,&parameterArray[0]);
                    510:                [driverLock unlock];
                    511:                r = IO_R_SUCCESS;
                    512:            }
                    513:        }
                    514:        else if (   strcmp( parameterName, EVSIOCCS ) == 0 )
                    515:        {
                    516:            if ( maxCount >= EVSIOCCS_SIZE )
                    517:            {
                    518:                returnedCount = EVSIOCCS_SIZE;
                    519:                [driverLock lock];
                    520:                parameterArray[EVSIOCCS_X] = clickSpaceThresh.x;
                    521:                parameterArray[EVSIOCCS_Y] = clickSpaceThresh.y;
                    522:                [driverLock unlock];
                    523:                r = IO_R_SUCCESS;
                    524:            }
                    525:        }
                    526:        else if (   strcmp( parameterName, EVSIOCADS ) == 0 )
                    527:        {
                    528:            if ( maxCount >= EVSIOCADS_SIZE )
                    529:            {
                    530:                returnedCount = EVSIOCADS_SIZE;
                    531:                [driverLock lock];
                    532:                parameterArray[0] = autoDimmed;
                    533:                [driverLock unlock];
                    534:                r = IO_R_SUCCESS;
                    535:            }
                    536:        }
                    537:        else if (   strcmp( parameterName, EVSIOINFO ) == 0 )
                    538:        {
                    539:            NXEventSystemDevice dp;
                    540:            unsigned int cnt;
                    541: 
                    542:            [eventSrcListLock lock];
                    543:            device = (attachedEventSrc *)queue_first(&eventSrcList);
                    544:            while( ! queue_end(&eventSrcList, (queue_t)device)
                    545:                  && maxCount >= (sizeof(NXEventSystemDevice) / sizeof(int)) )
                    546:            {
                    547:                srcInstance = device->info.eventSrc;
                    548:                device = (attachedEventSrc *)device->link.next;
                    549:                cnt = 0;
                    550:                retval = [srcInstance 
                    551:                            getIntValues:&parameterArray[returnedCount]
                    552:                           forParameter : parameterName
                    553:                                  count : &cnt];
                    554:                if ( retval == IO_R_SUCCESS )
                    555:                {
                    556:                        maxCount -= cnt;
                    557:                        returnedCount += cnt;
                    558:                }
                    559:            }
                    560:            [eventSrcListLock unlock];
                    561:            r = IO_R_SUCCESS;
                    562: 
                    563:        }
                    564:        else
                    565:        {
                    566:            // Try sending the operation out to the attached
                    567:            // event sources.
                    568:            returnedCount = *count;
                    569:            [eventSrcListLock lock];
                    570:            device = (attachedEventSrc *)queue_first(&eventSrcList);
                    571:            while(!queue_end(&eventSrcList, (queue_t)device))
                    572:            {
                    573:                srcInstance = device->info.eventSrc;
                    574:                device = (attachedEventSrc *)device->link.next;
                    575:                retval = [srcInstance getIntValues:parameterArray
                    576:                                    forParameter:parameterName
                    577:                                    count:&returnedCount];
                    578:                if ( retval != IO_R_INVALID_ARG )
                    579:                {
                    580:                    r = retval;
                    581:                    break;
                    582:                }
                    583:            }
                    584:            [eventSrcListLock unlock];
                    585: 
                    586:            if ( r == IO_R_INVALID_ARG )
                    587:            {
                    588:                r = [super getIntValues:parameterArray
                    589:                           forParameter : parameterName
                    590:                                  count : &returnedCount];
                    591:            }
                    592:        }
                    593:        *count = returnedCount;
                    594:        return r;
                    595: }
                    596: 
                    597: - (IOReturn)getCharValues              : (unsigned char *)parameterArray
                    598:                           forParameter : (IOParameterName)parameterName
                    599:                                  count : (unsigned *)count
                    600: {
                    601:        IOReturn r = IO_R_INVALID_ARG;
                    602:        IOReturn retval;
                    603:        attachedEventSrc *device;
                    604:        id      srcInstance;
                    605:        unsigned maxCount = *count;
                    606:        unsigned returnedCount = 0;
                    607:        
                    608:        if ( 0 )
                    609:        {
                    610:        }
                    611:        else
                    612:        {
                    613:                // Try sending the operation out to the attached
                    614:                // event sources.
                    615:                returnedCount = *count;
                    616:                [eventSrcListLock lock];
                    617:                device = (attachedEventSrc *)queue_first(&eventSrcList);
                    618:                while(!queue_end(&eventSrcList, (queue_t)device))
                    619:                {
                    620:                        srcInstance = device->info.eventSrc;
                    621:                        device = (attachedEventSrc *)device->link.next;
                    622:                        retval = [srcInstance getCharValues:parameterArray
                    623:                                            forParameter:parameterName
                    624:                                            count:&returnedCount];
                    625:                        if ( retval != IO_R_INVALID_ARG )
                    626:                        {
                    627:                                r = retval;
                    628:                                break;
                    629:                        }
                    630:                }
                    631:                [eventSrcListLock unlock];
                    632: 
                    633:                if ( r == IO_R_INVALID_ARG )
                    634:                {
                    635:                        r = [super getCharValues:parameterArray
                    636:                           forParameter : parameterName
                    637:                                  count : &returnedCount];
                    638:                }
                    639:        }
                    640:        *count = returnedCount;
                    641:        return r;
                    642: }
                    643: 
                    644:                
                    645: - (IOReturn)setIntValues               : (unsigned *)parameterArray
                    646:                           forParameter : (IOParameterName)parameterName
                    647:                                  count : (unsigned)count;
                    648: {
                    649:        IOReturn r = IO_R_INVALID_ARG;
                    650:        IOReturn retval;
                    651:        attachedEventSrc *device;
                    652:        id      srcInstance;
                    653:        Point           p;
                    654:        _NX_packed_event_t event;
                    655:        ns_time_t nst;
                    656: 
                    657:        if ( strcmp( parameterName, EVIOSETSCREEN ) == 0 )
                    658:        {
                    659:                if ( count == EVIOSETSCREEN_SIZE )
                    660:                    r = [self evSetScreen:parameterArray];
                    661:        }
                    662:        else if ( strcmp( parameterName, EVIOST ) == 0 )
                    663:        {
                    664:                [self startCursor];
                    665:                r = IO_R_SUCCESS;
                    666:        }
                    667:        else if ( strcmp( parameterName, EVIOSM ) == 0 )
                    668:        {
                    669:                if ( count == EVIOSM_SIZE )
                    670:                {
                    671:                        p.x = parameterArray[EVIOSM_LOC_X];
                    672:                        p.y = parameterArray[EVIOSM_LOC_Y];
                    673:                        [driverLock lock];
                    674:                        [self setCursorPosition:&p];
                    675:                        [driverLock unlock];
                    676:                        r = IO_R_SUCCESS;
                    677:                }
                    678:        }
                    679:        else if ( strcmp( parameterName, EVSIOSWT ) == 0 )
                    680:        {
                    681:                packed_nsecs_to_nsecs(parameterArray, &nst);            
                    682:                [driverLock lock];
                    683:                if ( eventsOpen )
                    684:                        ((EvGlobals*)evg)->waitThreshold = EV_NS_TO_TICK(nst);
                    685:                [driverLock unlock];
                    686:                r = IO_R_SUCCESS;
                    687:        }
                    688:        else if ( strcmp( parameterName, EVSIOSWS ) == 0 )
                    689:        {
                    690:                [driverLock lock];
                    691:                packed_nsecs_to_nsecs(parameterArray, &waitSustain);            
                    692:                [driverLock unlock];
                    693:                r = IO_R_SUCCESS;
                    694:        }
                    695:        else if ( strcmp( parameterName, EVSIOSWFI ) == 0 )
                    696:        {
                    697:                [driverLock lock];
                    698:                packed_nsecs_to_nsecs(parameterArray, &waitFrameRate);          
                    699:                [driverLock unlock];
                    700:                r = IO_R_SUCCESS;
                    701:        }
                    702:        else if ( strcmp( parameterName, EVSIOSB ) == 0 )
                    703:        {
                    704:                [driverLock lock];
                    705:                [self setBrightness:parameterArray[0]];
                    706:                [driverLock unlock];
                    707:                r = IO_R_SUCCESS;
                    708:        }
                    709:        else if ( strcmp( parameterName, EVSIOSA ) == 0 )
                    710:        {       // Obsolete once libc-67 is released
                    711:                [driverLock lock];
                    712:                [self setUserAudioVolume:parameterArray[0]];
                    713:                [driverLock unlock];
                    714:                r = IO_R_SUCCESS;
                    715:        }
                    716:        else if ( strcmp( parameterName, EVSIOSADB ) == 0 )
                    717:        {
                    718:                [driverLock lock];
                    719:                [self setAutoDimBrightness:parameterArray[0]];
                    720:                [driverLock unlock];
                    721:                r = IO_R_SUCCESS;
                    722:        }
                    723:        else if ( strcmp( parameterName, EVSIOSCT ) == 0 )
                    724:        {
                    725:                packed_nsecs_to_nsecs(parameterArray, &nst);            
                    726:                [driverLock lock];
                    727:                clickTimeThresh = EV_NS_TO_TICK(nst);
                    728:                [driverLock unlock];
                    729:                r = IO_R_SUCCESS;
                    730:        }
                    731:        else if ( strcmp( parameterName, EVSIOSCS ) == 0 )
                    732:        {
                    733:                [driverLock lock];
                    734:                clickSpaceThresh.x = parameterArray[EVSIOSCS_X];
                    735:                clickSpaceThresh.y = parameterArray[EVSIOSCS_Y];
                    736:                [driverLock unlock];
                    737:                r = IO_R_SUCCESS;
                    738:        }
                    739:        else if ( strcmp( parameterName, EVSIOSADT ) == 0 )
                    740:        {
                    741:                packed_nsecs_to_nsecs(parameterArray, &nst);            
                    742:                [driverLock lock];
                    743:                autoDimTime = autoDimTime - autoDimPeriod + EV_NS_TO_TICK(nst);
                    744:                autoDimPeriod = EV_NS_TO_TICK(nst);
                    745:                [driverLock unlock];
                    746:                r = IO_R_SUCCESS;
                    747:        }
                    748:        else if ( strcmp( parameterName, EVSIOSADS ) == 0 )
                    749:        {
                    750:                [driverLock lock];
                    751:                [self forceAutoDimState:parameterArray[0]];
                    752:                [driverLock unlock];
                    753:                r = IO_R_SUCCESS;
                    754:        }
                    755:        else if ( strcmp( parameterName, EVSIORMS ) == 0 )
                    756:        {
                    757:                [self _resetMouseParameters];
                    758:                r = IO_R_SUCCESS;
                    759:        }
                    760:        else if ( strcmp( parameterName, EVSIORKBD ) == 0 )
                    761:        {
                    762:                [self _resetKeyboardParameters];
                    763:                r = IO_R_SUCCESS;
                    764:        }
                    765:        else if (  strcmp( parameterName, EVIOLLPE ) == 0 
                    766:                || strcmp( parameterName, EVIOPTRLLPE ) == 0 )
                    767:        {
                    768:                if ( count == EVIOLLPE_SIZE )
                    769:                {
                    770:                        p.x = parameterArray[EVIOLLPE_LOC_X];
                    771:                        p.y = parameterArray[EVIOLLPE_LOC_Y];
                    772:                        event.idata[0] = parameterArray[EVIOLLPE_DATA0];
                    773:                        event.idata[1] = parameterArray[EVIOLLPE_DATA1];
                    774:                        event.idata[2] = parameterArray[EVIOLLPE_DATA2];
                    775:                        [driverLock lock];
                    776:                        if ( strcmp( parameterName, EVIOPTRLLPE ) == 0 )
                    777:                                [self setCursorPosition:&p];
                    778:                        [self postEvent:parameterArray[EVIOLLPE_TYPE]
                    779:                                at:&p
                    780:                                atTime:EvTickTimeValue()
                    781:                                withData:&event.data];          
                    782:                        [driverLock unlock];
                    783:                        r = IO_R_SUCCESS;
                    784:                }
                    785:        }
                    786:        else
                    787:        {
                    788:                // Try sending the operation out to the attached
                    789:                // event sources.
                    790:                [eventSrcListLock lock];
                    791:                device = (attachedEventSrc *)queue_first(&eventSrcList);
                    792:                while(!queue_end(&eventSrcList, (queue_t)device))
                    793:                {
                    794:                        srcInstance = device->info.eventSrc;
                    795:                        device = (attachedEventSrc *)device->link.next;
                    796:                        retval = [srcInstance setIntValues:parameterArray
                    797:                                            forParameter:parameterName
                    798:                                            count:count];
                    799:                        if ( retval != IO_R_INVALID_ARG )
                    800:                                r = retval;
                    801:                }
                    802:                [eventSrcListLock unlock];
                    803: 
                    804:                // Nobody wants it?  Kick the message upstairs.
                    805:                if ( r == IO_R_INVALID_ARG )
                    806:                {
                    807:                        r = [super setIntValues:parameterArray
                    808:                                            forParameter:parameterName
                    809:                                            count:count];
                    810:                }
                    811:        }
                    812:        return r;
                    813: }
                    814: 
                    815: - (IOReturn)setCharValues              : (unsigned char *)parameterArray
                    816:                           forParameter : (IOParameterName)parameterName
                    817:                                  count : (unsigned)count;
                    818: {
                    819:        IOReturn r = IO_R_INVALID_ARG;
                    820:        IOReturn retval;
                    821:        attachedEventSrc *device;
                    822:        id      srcInstance;
                    823: 
                    824:        if ( 0 )
                    825:        {
                    826:        }
                    827:        else
                    828:        {
                    829:                // Try sending the operation out to the attached
                    830:                // event sources.
                    831:                [eventSrcListLock lock];
                    832:                device = (attachedEventSrc *)queue_first(&eventSrcList);
                    833:                while(!queue_end(&eventSrcList, (queue_t)device))
                    834:                {
                    835:                        srcInstance = device->info.eventSrc;
                    836:                        device = (attachedEventSrc *)device->link.next;
                    837:                        retval = [srcInstance setCharValues:parameterArray
                    838:                                                forParameter:parameterName
                    839:                                                count:count];
                    840:                        if ( retval != IO_R_INVALID_ARG )
                    841:                                r = retval;
                    842:                }
                    843:                [eventSrcListLock unlock];
                    844: 
                    845:                if ( r == IO_R_INVALID_ARG )
                    846:                {
                    847:                        r = [super setCharValues: parameterArray
                    848:                                        forParameter:parameterName
                    849:                                        count:count];
                    850:                }
                    851:        }
                    852:        return r;
                    853: }
                    854: 
                    855: //
                    856: // Reset instance variables to their default state for mice/pointers
                    857: //
                    858: - _resetMouseParameters
                    859: {
                    860:        attachedEventSrc *device;
                    861:        id      srcInstance;
                    862:        unsigned int parameterArray[EVSIORMS_SIZE];
                    863: 
                    864:        [driverLock lock];
                    865:        if ( eventsOpen == NO )
                    866:        {
                    867:            [driverLock unlock];
                    868:            return self;
                    869:        }
                    870:        clickTimeThresh = EV_DCLICKTIME;
                    871:        clickSpaceThresh.x = clickSpaceThresh.y = EV_DCLICKSPACE;
                    872:        clickTime = -EV_DCLICKTIME;
                    873:        clickLoc.x = clickLoc.y = -EV_DCLICKSPACE;
                    874:        clickState = 1;
                    875:        autoDimTime = ((EvGlobals*)evg)->VertRetraceClock + DAUTODIMPERIOD;
                    876:        autoDimPeriod = DAUTODIMPERIOD;
                    877:        dimmedBrightness = DDIMBRIGHTNESS;
                    878: 
                    879:        [driverLock unlock];
                    880:        // Go down the Event Src list looking for devices which respond to
                    881:        // a EVSIORMS message.  Ping these.
                    882:        [eventSrcListLock lock];
                    883:        device = (attachedEventSrc *)queue_first(&eventSrcList);
                    884:        while(!queue_end(&eventSrcList, (queue_t)device))
                    885:        {
                    886:                srcInstance = device->info.eventSrc;
                    887:                device = (attachedEventSrc *)device->link.next;
                    888:                [srcInstance setIntValues:parameterArray
                    889:                                    forParameter:EVSIORMS
                    890:                                    count:EVSIORMS_SIZE];
                    891:        }
                    892:        [eventSrcListLock unlock];
                    893: 
                    894:        return self;
                    895: }
                    896: 
                    897: - _resetKeyboardParameters
                    898: {
                    899:        attachedEventSrc *device;
                    900:        id      srcInstance;
                    901:        unsigned int parameterArray[EVSIORKBD_SIZE];
                    902: 
                    903:        // Go down the Event Src list looking for devices which respond to
                    904:        // a EVSIORKBD message.  Ping these.
                    905:        [eventSrcListLock lock];
                    906:        device = (attachedEventSrc *)queue_first(&eventSrcList);
                    907:        while(!queue_end(&eventSrcList, (queue_t)device))
                    908:        {
                    909:                srcInstance = device->info.eventSrc;
                    910:                device = (attachedEventSrc *)device->link.next;
                    911:                [srcInstance setIntValues:parameterArray
                    912:                                    forParameter:EVSIORKBD
                    913:                                    count:EVSIORKBD_SIZE];
                    914:        }
                    915:        [eventSrcListLock unlock];
                    916:        return self;
                    917: }
                    918: 
                    919: /*
                    920:  * Methods exported by the EventDriver.
                    921:  *
                    922:  *     The screenRegister protocol is used by frame buffer drivers to register
                    923:  *     themselves with the Event Driver.  These methods are called in response
                    924:  *     to a registerSelf or unregisterSelf message received from the Event
                    925:  *     Driver.
                    926:  */
                    927: /* @protocol screenRegister */
                    928: 
                    929: - (int) registerScreen:        (id)instance
                    930:                bounds:(Bounds *)bp
                    931:                shmem:(void **)addr
                    932:                size:(int *)size
                    933: {
                    934:     EvScreen *esp;
                    935: 
                    936:     if ( eventsOpen == NO )
                    937:     {
                    938:        *addr = (void *)0;
                    939:        *size = 0;
                    940:        return -1;
                    941:     }
                    942:     if ( lastShmemPtr == (void *)0 )
                    943:        lastShmemPtr = evs;
                    944:     
                    945:     /* shmemSize and bounds already set */
                    946:     esp = &((EvScreen*)evScreen)[screens];
                    947:     esp->instance = instance;
                    948:     /* If this driver wants private shmem, then set its shmemPtr */
                    949:     if (esp->shmemSize)
                    950:        esp->shmemPtr = lastShmemPtr;
                    951:     lastShmemPtr += esp->shmemSize;
                    952:     /* Fill in parameters for the requesting instance */
                    953:     *addr = esp->shmemPtr;
                    954:     *size = esp->shmemSize;
                    955:     bcopy( (char *)&esp->bounds, (char *)bp, sizeof (Bounds) );
                    956:     return(SCREENTOKEN + screens++);
                    957: }
                    958: 
                    959: 
                    960: - (void) unregisterScreen:(int)index
                    961: {
                    962:     int i;
                    963: 
                    964:     index -= SCREENTOKEN;
                    965: 
                    966:     [driverLock lock];
                    967:     if ( eventsOpen == NO || index < 0 || index >= screens )
                    968:     {
                    969:        [driverLock unlock];
                    970:        return;
                    971:     }
                    972:     [self hideCursor];
                    973:     // clear the state for the screen
                    974:     ((EvScreen*)evScreen)[index].instance = nil;
                    975:     // Put the cursor someplace reasonable if it was on the destroyed screen
                    976:     if ( currentScreen == index )      // Uh oh...
                    977:     {
                    978:        for ( i = screens; --i != -1; ) // Pick a new currentScreen
                    979:        {
                    980:            if ( ((EvScreen*)evScreen)[i].instance != nil )
                    981:            {
                    982:                currentScreen = i;
                    983:                break;
                    984:            }
                    985:        }
                    986:        // This will jump the cursor back on screen
                    987:        [self setCursorPosition:(Point *)&((EvGlobals*)evg)->cursorLoc];
                    988:     }
                    989:     else
                    990:        [self showCursor];
                    991:     [driverLock unlock];
                    992:     return;
                    993: }
                    994: 
                    995: /* @end screenRegister */
                    996: 
                    997: /* Private methods specific to this driver */   
                    998: 
                    999: #if KERNEL
                   1000: //
                   1001: // Allocate a private array of EvScreen structures based on the screen count
                   1002: // passed in by PostScript and copy in each screen's bounds and shmemSize.
                   1003: // Also calculate the total size of shared memory and return it to PostScript.
                   1004: // PostScript will later call mapEventShmem to map in the page(s) at which
                   1005: // point the ev driver will fill out the EvOffsets structure partly
                   1006: // based on each driver's shmemSize.  NOTE: Can't access evg pointer yet!
                   1007: //
                   1008: 
                   1009: - (IOReturn)evSetScreen:(unsigned int *)parameterArray
                   1010: {
                   1011:     int i = parameterArray[EVIOSETSCREEN_INDEX];
                   1012:     EvScreen * screen;
                   1013: 
                   1014:     if ( evOpenCalled == NO )  // Try to screen out cruft...
                   1015:        return IO_R_PRIVILEGE;
                   1016: 
                   1017:     if (!evScreen) {
                   1018:        /* if first time through, allocate screen array */
                   1019:        evScreenSize = sizeof(EvScreen)
                   1020:                        * parameterArray[EVIOSETSCREEN_TOTALSCREENS];
                   1021:        evScreen = (void *) IOMalloc(evScreenSize);
                   1022:        bzero(evScreen, evScreenSize);
                   1023:        /* The following initial shmem size can change in the kernel if
                   1024:         * more space is required.  This lets the kernel shmem structure
                   1025:         * expand if needed without breaking PostScript.
                   1026:         */
                   1027:        shmem_size = sizeof(EvGlobals) + sizeof(EvOffsets);
                   1028:        // Set up screen registration variables
                   1029:        lastShmemPtr = (void *)0;
                   1030:        screens = 0;
                   1031:        workSpace.minx = workSpace.miny = workSpace.maxx = workSpace.maxy = 0;
                   1032:     }
                   1033:     if ( i < 0 || i >= (evScreenSize / sizeof(EvScreen)) )     // Sanity check
                   1034:        return IO_R_INVALID_ARG;
                   1035:     screen = &((EvScreen*)evScreen)[i];
                   1036:     screen->bounds.minx = parameterArray[EVIOSETSCREEN_MINX];
                   1037:     screen->bounds.maxx = parameterArray[EVIOSETSCREEN_MAXX];
                   1038:     screen->bounds.miny = parameterArray[EVIOSETSCREEN_MINY];
                   1039:     screen->bounds.maxy = parameterArray[EVIOSETSCREEN_MAXY];
                   1040:     screen->shmemSize = parameterArray[EVIOSETSCREEN_SHMEMSIZE];
                   1041:     shmem_size += parameterArray[EVIOSETSCREEN_SHMEMSIZE];
                   1042:     // Update our idea of workSpace bounds
                   1043:     if ( screen->bounds.minx < workSpace.minx )
                   1044:        workSpace.minx = screen->bounds.minx;
                   1045:     if ( screen->bounds.miny < workSpace.miny )
                   1046:        workSpace.miny = screen->bounds.miny;
                   1047:     if ( screen->bounds.maxx < workSpace.maxx )
                   1048:        workSpace.maxx = screen->bounds.maxx;
                   1049:     if ( screen->bounds.maxy < workSpace.maxy )
                   1050:        workSpace.maxy = screen->bounds.maxy;
                   1051:     return IO_R_SUCCESS;
                   1052: }
                   1053: 
                   1054: /* Member of EventClient protocol 
                   1055:  *
                   1056:  * Absolute position input devices and some specialized output devices
                   1057:  * may need to know the bounding rectangle for all attached displays.
                   1058:  * The following method returns a Bounds* for the workspace.  Please note
                   1059:  * that the bounds are kept as signed values, and that on a multi-display
                   1060:  * system the minx and miny values may very well be negative.
                   1061:  */
                   1062: - (Bounds *)workspaceBounds
                   1063: {
                   1064:        return &workSpace;
                   1065: }
                   1066: 
                   1067: /*
                   1068:  * Set up the shared memory area between the Window Server and the kernel.
                   1069:  *
                   1070:  *     Obtain page aligned wired kernel memory for 'size' bytes using
                   1071:  *     kmem_alloc().
                   1072:  *     Find a similar sized region in the Window Server task VM map using
                   1073:  *     vm_map_find().  This function will find an appropriately sized region,
                   1074:  *     create a memory object, and insert it in the VM map.
                   1075:  *     For each physical page in the kernel's wired memory we got from
                   1076:  *     kmem_alloc(), enter that page at the appropriate location in the page
                   1077:  *     map for the Window Server, in the address range we allocated using
                   1078:  *     vm_map_find().  
                   1079:  */
                   1080: - (IOReturn) mapEventShmem : (port_t) event_port
                   1081:                   task : (port_t)task                  // in
                   1082:                   size : (vm_size_t)size               // in
                   1083:                   at : (vm_offset_t *)addr             // out
                   1084: {
                   1085:        vm_offset_t     off;
                   1086:        vm_offset_t     phys_addr;
                   1087:        IOReturn        krtn;
                   1088:        void *          task_map;
                   1089:        vm_offset_t     task_addr;
                   1090:        
                   1091:        if ( event_port != eventPort || evOpenCalled == NO )
                   1092:            return IO_R_PRIVILEGE;
                   1093:        if ( task == PORT_NULL || size == 0 )   // malformed request
                   1094:            return IO_R_INVALID_ARG;
                   1095:        if ( owner_task != PORT_NULL || owner != NULL )
                   1096:            return IO_R_INVALID_ARG;    // Mapping set up already
                   1097: 
                   1098:        krtn = createEventShmem(task,size,&task_map,&task_addr,&shmem_addr);
                   1099:        if ( krtn != KERN_SUCCESS )
                   1100:        {
                   1101:            IOLog("%s: createEventShmem fails (%d).\n",[self name],krtn);
                   1102:            return krtn;
                   1103:        }
                   1104: 
                   1105:        [driverLock lock];
                   1106:        shmem_size = size;
                   1107:        owner_task = task;
                   1108:        owner_addr = task_addr;
                   1109:        *addr = task_addr;
                   1110:        owner = task_map;
                   1111:        [self initShmem];
                   1112:        [driverLock unlock];
                   1113: 
                   1114:        [self _resetMouseParameters];
                   1115:        [self _resetKeyboardParameters];
                   1116:        // Start the cursor control callouts
                   1117:        [driverLock lock];
                   1118:        [self scheduleNextPeriodicEvent];
                   1119:        [driverLock unlock];
                   1120: 
                   1121:        return IO_R_SUCCESS;
                   1122: }
                   1123: 
                   1124: // 
                   1125: // Unmap the shared memory area and release the wired memory.
                   1126: //
                   1127: - (IOReturn) unmapEventShmem : (port_t)event_port;
                   1128: {
                   1129:        vm_offset_t off;
                   1130:        IOReturn r;
                   1131: 
                   1132:        // Since the shared memory area is being torn down, set eventsOpen
                   1133:        // to NO to keep the cursor thread from futzing with the shared area.
                   1134:        // We need to implement a lock to guard the shmem, and acquire the
                   1135:        // lock before tearing the area down.
                   1136:        xpr_ev_shmemlock("unmapEventShmem: will lock %x\n",
                   1137:                        driverLock, 3, 4, 5, 6);
                   1138:        [driverLock lock];
                   1139:        xpr_ev_shmemlock("unmapEventShmem: did lock %x\n",
                   1140:                        driverLock, 3, 4, 5, 6);
                   1141: 
                   1142:        if (event_port != eventPort || evOpenCalled == NO || eventsOpen == NO)
                   1143:        {
                   1144:            [driverLock unlock];
                   1145:            return IO_R_PRIVILEGE;
                   1146:        }
                   1147:        eventsOpen = NO;
                   1148: 
                   1149:        r=destroyEventShmem(owner_task,owner,shmem_size,owner_addr,shmem_addr);
                   1150:        if ( r != KERN_SUCCESS )
                   1151:        {
                   1152:            IOLog("%s: destroyEventShmem fails (%d).\n", [self name], r);
                   1153:        }
                   1154:        shmem_addr = owner_addr = (vm_offset_t)0;
                   1155:        shmem_size = 0;
                   1156:        owner = NULL;
                   1157:        owner_task = PORT_NULL;
                   1158:        [driverLock unlock];
                   1159:        xpr_ev_shmemlock("unmapEventShmem: did unlock %x\n",
                   1160:                        driverLock, 3, 4, 5, 6);
                   1161:        return r;
                   1162: }
                   1163: #endif
                   1164: 
                   1165: // Initialize the shared memory area.
                   1166: //
                   1167: // On entry, the driverLock should be set.
                   1168: - initShmem
                   1169: {
                   1170:        int             i;
                   1171:        EvOffsets       *eop;
                   1172:        EvGlobals       *glob;
                   1173: 
                   1174:        pointerLoc.x = INIT_CURSOR_X;
                   1175:        pointerLoc.y = INIT_CURSOR_Y;
                   1176: 
                   1177:        /* top of sharedMem is EvOffsets structure */
                   1178:        eop = (EvOffsets *) shmem_addr;
                   1179:        
                   1180:        /* fill in EvOffsets structure */
                   1181:        eop->evGlobalsOffset = sizeof(EvOffsets);
                   1182:        eop->evShmemOffset = eop->evGlobalsOffset + sizeof(EvGlobals);
                   1183:     
                   1184:        /* find pointers to start of globals and private shmem region */
                   1185:        glob = (EvGlobals *) ((char *)shmem_addr + eop->evGlobalsOffset);
                   1186:        evs = (void *)((char *)shmem_addr + eop->evShmemOffset);
                   1187:     
                   1188:        /* Set default wait cursor parameters */
                   1189:        glob->waitCursorEnabled = TRUE;
                   1190:        glob->globalWaitCursorEnabled = TRUE;
                   1191:        glob->waitThreshold = EV_NS_TO_TICK(DefaultWCThreshold);
                   1192:        waitFrameRate = DefaultWCFrameRate;
                   1193:        waitSustain = DefaultWCSustain; 
                   1194:        waitSusTime = 0ULL;
                   1195:        waitFrameTime = 0ULL;
                   1196: 
                   1197:        /* Set up low-level queues */
                   1198:        lleqSize = LLEQSIZE;
                   1199:        for (i=lleqSize; --i != -1; ) {
                   1200:            glob->lleq[i].event.type = 0;
                   1201:            glob->lleq[i].event.time = 0;
                   1202:            glob->lleq[i].event.flags = 0;
                   1203:            ev_init_lock(&glob->lleq[i].sema);
                   1204:            glob->lleq[i].next = i+1;
                   1205:        }
                   1206:        glob->LLELast = 0;
                   1207:        glob->lleq[lleqSize-1].next = 0;
                   1208:        glob->LLEHead =
                   1209:            glob->lleq[glob->LLELast].next;
                   1210:        glob->LLETail =
                   1211:            glob->lleq[glob->LLELast].next;
                   1212:        glob->buttons = 0;
                   1213:        glob->eNum = INITEVENTNUM;
                   1214:        glob->eventFlags = 0;
                   1215:        glob->VertRetraceClock = EvTickTimeValue();
                   1216:        glob->cursorLoc = pointerLoc;
                   1217:        glob->dontCoalesce = 0;
                   1218:        glob->dontWantCoalesce = 0;
                   1219:        glob->wantPressure = 0;
                   1220:        glob->wantPrecision = 0;
                   1221:        glob->mouseRectValid = 0;
                   1222:        glob->movedMask = 0;
                   1223:        ev_init_lock( &glob->cursorSema );
                   1224:        ev_init_lock( &glob->waitCursorSema );
                   1225:        evg = (void *)glob;
                   1226:        // Set eventsOpen last to avoid race conditions.
                   1227:        eventsOpen = YES;
                   1228:        
                   1229:        return self;
                   1230: }
                   1231: 
                   1232: //
                   1233: // Set the event port.  The event port is both an ownership token
                   1234: // and a live port we hold send rights on.  The port is owned by our client,
                   1235: // the WindowServer.  We arrange to be notified on a port death so that
                   1236: // we can tear down any active resources set up during this session.
                   1237: // An argument of PORT_NULL will cause us to forget any port death
                   1238: // notification that's set up.
                   1239: //
                   1240: // The driverLock should be held on entry.
                   1241: //
                   1242: - setEventPort:(port_t)port
                   1243: {
                   1244:        static struct _eventMsg init_msg =
                   1245:                        { { 0, 1, sizeof(msg_header_t)+sizeof(msg_type_t), 
                   1246:                           MSG_TYPE_NORMAL, (port_t)0, (port_t)0, 0 },
                   1247:                          { MSG_TYPE_UNSTRUCTURED, 0, 0, 1, 0, 0 } };
                   1248:        if ( port == PORT_NULL )
                   1249:        {
                   1250:                event_kern_port = (port_t)KERN_PORT_NULL;
                   1251:        }
                   1252:        else if ( port != eventPort )   // Set up a new notification
                   1253:        {
                   1254:                event_kern_port = IOGetKernPort(port);
                   1255:                port_request_notification((kern_port_t)event_kern_port, 
                   1256:                        (kern_port_t)notify_kern_port);
                   1257:        }
                   1258:        if ( eventMsg == NULL )
                   1259:                eventMsg = IOMalloc( sizeof (struct _eventMsg) );
                   1260:        eventPort = port;
                   1261:        // Initialize the events available message.
                   1262:        *((struct _eventMsg *)eventMsg) = init_msg;
                   1263: 
                   1264:        ((struct _eventMsg *)eventMsg)->h.msg_remote_port = port;
                   1265:        return self;
                   1266: }
                   1267: 
                   1268: //
                   1269: // Set the port to be used for a special key notification.  This could be more
                   1270: // robust about letting ports be set...
                   1271: //
                   1272: - (IOReturn)   setSpecialKeyPort       : (port_t)dev_port
                   1273:                                keyFlavor       : (int)special_key
                   1274:                                keyPort         : (port_t)key_port
                   1275: {
                   1276:        if ( dev_port != ev_port )
                   1277:            return IO_R_PRIVILEGE;
                   1278:        
                   1279:        if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS )
                   1280:                specialKeyPort[special_key] = key_port;
                   1281:        return IO_R_SUCCESS;
                   1282: }
                   1283: 
                   1284: - (port_t)specialKeyPort: (int)special_key
                   1285: {
                   1286:        if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS )
                   1287:                return specialKeyPort[special_key];
                   1288:        return PORT_NULL;
                   1289: }
                   1290: 
                   1291: //     Return ports used for Mach interface
                   1292: - (port_t)ev_port
                   1293: { 
                   1294:        return ev_port;
                   1295: }
                   1296: 
                   1297: - (port_t)evs_port
                   1298: {
                   1299:        return evs_port;
                   1300: }
                   1301: 
                   1302: //
                   1303: // Dispatch mechanism for special key press.  If a port has been registered,
                   1304: // a message is built to be sent out to that port notifying that the key has
                   1305: // changed state.  A level in the range 0-64 is provided for convenience.
                   1306: //
                   1307: - evSpecialKeyMsg:     (unsigned)key
                   1308:                        direction:(unsigned)dir
                   1309:                        flags:(unsigned)f
                   1310:                        level:(unsigned)l
                   1311: {
                   1312:        port_t dst_port;
                   1313:        struct evioSpecialKeyMsg *msg;
                   1314:        static const struct evioSpecialKeyMsg init_msg =
                   1315:                        { { 0, 1, sizeof (struct evioSpecialKeyMsg), 
                   1316:                           MSG_TYPE_NORMAL, (port_t)0, (port_t)0,
                   1317:                          EV_SPECIAL_KEY_MSG_ID },
                   1318:                          { MSG_TYPE_INTEGER_32, 32, 1, TRUE, FALSE, FALSE },
                   1319:                          0,    /* key */
                   1320:                          { MSG_TYPE_INTEGER_32, 32, 1, TRUE, FALSE, FALSE },
                   1321:                          0,    /* direction */
                   1322:                          { MSG_TYPE_INTEGER_32, 32, 1, TRUE, FALSE, FALSE },
                   1323:                          0,    /* flags */
                   1324:                          { MSG_TYPE_INTEGER_32, 32, 1, TRUE, FALSE, FALSE },
                   1325:                          0     /* level */
                   1326:                        };
                   1327: 
                   1328:        if ( (dst_port = [self specialKeyPort:key]) == PORT_NULL )
                   1329:                return self;
                   1330:        msg = (struct evioSpecialKeyMsg *) IOMalloc(
                   1331:                                sizeof (struct evioSpecialKeyMsg) );
                   1332:        if ( msg == NULL )
                   1333:                return self;
                   1334:        
                   1335:        // Initialize the message.
                   1336:        bcopy( &init_msg, msg, sizeof (struct evioSpecialKeyMsg) );
                   1337:        msg->Head.msg_remote_port = dst_port;
                   1338:        msg->key = key;
                   1339:        msg->direction = dir;
                   1340:        msg->flags = f;
                   1341:        msg->level = l;
                   1342: 
                   1343:        // Send the message out from the I/O thread.
                   1344:        [self sendIOThreadAsyncMsg      :@selector(_performSpecialKeyMsg:)
                   1345:                        to              :self
                   1346:                        with            :(void *)msg];
                   1347: 
                   1348:        return self;
                   1349: }
                   1350: 
                   1351: /*
                   1352:  * This is run in the I/O thread, to perform the actual message send operation.
                   1353:  */
                   1354: - _performSpecialKeyMsg:(id)data
                   1355: {
                   1356:        kern_return_t r;
                   1357:        struct evioSpecialKeyMsg *msg;
                   1358: 
                   1359:        msg = (struct evioSpecialKeyMsg *)data;
                   1360:        xpr_ev_post("_performSpecialKeyMsg 0x%x\n", msg,2,3,4,5);
                   1361: 
                   1362:        r = msg_send( &msg->Head, SEND_TIMEOUT, 0 );    /* Don't block */
                   1363:        xpr_ev_post("_performSpecialKeyMsg: msg_send() == %d\n",
                   1364:                r,2,3,4,5);
                   1365:        if ( r != SEND_SUCCESS )
                   1366:        {
                   1367:                IOLog("%s: _performSpecialKeyMsg msg_send returned %d\n",
                   1368:                        [self name], r);
                   1369:        }
                   1370:        if ( r == SEND_INVALID_PORT )   /* Invalidate the port */
                   1371:        {
                   1372:                [self setSpecialKeyPort         : ev_port
                   1373:                                keyFlavor       : msg->key
                   1374:                                keyPort         : PORT_NULL];
                   1375:        }
                   1376:        IOFree( (void *)msg, sizeof (struct evioSpecialKeyMsg) );
                   1377:        return self;
                   1378: }
                   1379: 
                   1380: //
                   1381: // Dispatch state to screens registered with the Event Driver
                   1382: // Pending state changes for a device may be coalesced.
                   1383: //
                   1384: //
                   1385: // On entry, the  driverLock should be set.
                   1386: //
                   1387: - evDispatch:(int)screen command:(EvCmd)evcmd
                   1388: {
                   1389:     Point p;
                   1390:     EvScreen *esp = &((EvScreen*)evScreen)[screen];
                   1391: 
                   1392:     if ( eventsOpen == NO )
                   1393:        return self;
                   1394: 
                   1395:     p = ((EvGlobals*)evg)->cursorLoc;  // Copy from shmem.
                   1396:     if ( esp->instance != nil )
                   1397:     {
                   1398:        switch ( evcmd )
                   1399:        {
                   1400:            case EVMOVE:
                   1401:                [esp->instance  moveCursor:&p
                   1402:                                frame:((EvGlobals*)evg)->frame
                   1403:                                token:(screen + SCREENTOKEN)];
                   1404:                break;
                   1405: 
                   1406:            case EVSHOW:
                   1407:                [esp->instance  showCursor:&p
                   1408:                                frame:((EvGlobals*)evg)->frame
                   1409:                                token:(screen + SCREENTOKEN)];
                   1410:                break;
                   1411: 
                   1412:            case EVHIDE:
                   1413:                [esp->instance hideCursor:(screen + SCREENTOKEN)];
                   1414:                break;
                   1415: 
                   1416:            case EVLEVEL:
                   1417:                [esp->instance  setBrightness:[self currentBrightness]
                   1418:                                token:(screen + SCREENTOKEN)];
                   1419:        }
                   1420:     }
                   1421:     return self;
                   1422: }
                   1423: 
                   1424: //
                   1425: // Helper functions for postEvent
                   1426: //
                   1427: static inline int myAbs(int a) { return(a > 0 ? a : -a); }
                   1428: 
                   1429: static inline short UniqueEventNum(EventDriver * instance)
                   1430: {
                   1431:    EvGlobals *evg = (EvGlobals *)instance->evg;
                   1432:     while (++evg->eNum == NULLEVENTNUM)
                   1433:        ; /* sic */
                   1434:     return(evg->eNum);
                   1435: }
                   1436: 
                   1437: // postEvent 
                   1438: //
                   1439: // This routine actually places events in the event queue which is in
                   1440: // the EvGlobals structure.  It is called from all parts of the ev
                   1441: // driver.
                   1442: //
                   1443: // On entry, the driverLock should be set.
                   1444: //
                   1445: 
                   1446: - postEvent:(int)what
                   1447:        at:(Point *)location
                   1448:        atTime:(unsigned)theClock
                   1449:        withData:(NXEventData *)myData
                   1450: {
                   1451:     EvGlobals *glob = (EvGlobals *)evg;
                   1452:     NXEQElement        *theHead = (NXEQElement *) &glob->lleq[glob->LLEHead];
                   1453:     NXEQElement        *theLast = (NXEQElement *) &glob->lleq[glob->LLELast];
                   1454:     NXEQElement        *theTail = (NXEQElement *) &glob->lleq[glob->LLETail];
                   1455:     int                wereEvents;
                   1456: 
                   1457:     /* Some events affect screen dimming */
                   1458:     if (EventCodeMask(what) & NX_UNDIMMASK) {
                   1459:        autoDimTime = theClock + autoDimPeriod;
                   1460:        if (autoDimmed)
                   1461:            [self undoAutoDim];
                   1462:     }
                   1463:     // Update the PS VertRetraceClock off of the timestamp if it looks sane
                   1464:     if (   theClock > glob->VertRetraceClock
                   1465:        && theClock < (glob->VertRetraceClock + (20 * EV_TICK_TIME)) )
                   1466:        glob->VertRetraceClock = theClock;
                   1467: 
                   1468:     wereEvents = EventsInQueue();
                   1469: 
                   1470:     xpr_ev_post("postEvent: what %d, X %d Y %d Q %d, needKick %d\n",
                   1471:                what,location->x,location->y,
                   1472:                EventsInQueue(), needToKickEventConsumer);
                   1473: 
                   1474:     if ((!glob->dontCoalesce)  /* Coalescing enabled */
                   1475:     && (theHead != theTail)
                   1476:     && (theLast->event.type == what)
                   1477:     && (EventCodeMask(what) & COALESCEEVENTMASK)
                   1478:     && ev_try_lock(&theLast->sema)) {
                   1479:     /* coalesce events */
                   1480:        theLast->event.location.x = location->x;
                   1481:        theLast->event.location.y = location->y;
                   1482:        theLast->event.time = theClock;
                   1483:        if (myData != NULL)
                   1484:            theLast->event.data = *myData;
                   1485:        ev_unlock(&theLast->sema);
                   1486:     } else if (theTail->next != glob->LLEHead) {
                   1487:        /* store event in tail */
                   1488:        theTail->event.type = what;
                   1489:        theTail->event.location.x = location->x;
                   1490:        theTail->event.location.y = location->y;
                   1491:        theTail->event.flags = glob->eventFlags;
                   1492:        theTail->event.time = theClock;
                   1493:        theTail->event.window = 0;
                   1494:        if (myData != NULL)
                   1495:            theTail->event.data = *myData;
                   1496:        switch(what) {
                   1497:        case NX_LMOUSEDOWN:
                   1498:            theTail->event.data.mouse.eventNum =
                   1499:                leftENum = UniqueEventNum(self);
                   1500:            break;
                   1501:        case NX_RMOUSEDOWN:
                   1502:            theTail->event.data.mouse.eventNum =
                   1503:                rightENum = UniqueEventNum(self);
                   1504:            break;
                   1505:        case NX_LMOUSEUP:
                   1506:            theTail->event.data.mouse.eventNum = leftENum;
                   1507:            leftENum = NULLEVENTNUM;
                   1508:            break;
                   1509:        case NX_RMOUSEUP:
                   1510:            theTail->event.data.mouse.eventNum = rightENum;
                   1511:            rightENum = NULLEVENTNUM;
                   1512:            break;
                   1513:        }
                   1514:        if (EventCodeMask(what) & PRESSUREEVENTMASK) {
                   1515:            theTail->event.data.mouse.pressure = lastPressure;
                   1516:        }
                   1517:        if (EventCodeMask(what) & MOUSEEVENTMASK) { /* Click state */
                   1518:            if (((theClock - clickTime) <= clickTimeThresh)
                   1519:            && (myAbs(location->x - clickLoc.x) <= clickSpaceThresh.x)
                   1520:            && (myAbs(location->y - clickLoc.y) <= clickSpaceThresh.y)) {
                   1521:                theTail->event.data.mouse.click = 
                   1522:                    ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) ?
                   1523:                    (clickTime=theClock,++clickState) : clickState ;
                   1524:            } else if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) {
                   1525:                clickLoc = *location;
                   1526:                clickTime = theClock;
                   1527:                clickState = 1;
                   1528:                theTail->event.data.mouse.click = clickState;
                   1529:            } else
                   1530:                theTail->event.data.mouse.click = 0;
                   1531:        }
                   1532: #if PMON
                   1533:        pmon_log_event(PMON_SOURCE_EV,
                   1534:                       KP_EV_POST_EVENT,
                   1535:                       what,
                   1536:                       glob->eventFlags,
                   1537:                       theClock);
                   1538: #endif
                   1539:        glob->LLETail = theTail->next;
                   1540:        glob->LLELast = theLast->next;
                   1541:        if ( ! wereEvents )     // Events available, so wake event consumer
                   1542:            [self kickEventConsumer];
                   1543:     }
                   1544:     else
                   1545:     {
                   1546:        /*
                   1547:         * if queue is full, ignore event, too hard to take care of all cases 
                   1548:         */
                   1549:        IOLog("%s: postEvent LLEventQueue overflow.\n", [self name]);
                   1550:        [self kickEventConsumer];
                   1551: #if PMON
                   1552:        pmon_log_event( PMON_SOURCE_EV,
                   1553:                        KP_EV_QUEUE_FULL,
                   1554:                        what,
                   1555:                        glob->eventFlags,
                   1556:                        theClock);
                   1557: #endif
                   1558:     }
                   1559: }
                   1560: 
                   1561: /*
                   1562:  * - kickEventConsumer
                   1563:  *
                   1564:  *     Try to send a message out to let the event consumer know that
                   1565:  *     there are now events available for consumption.
                   1566:  */
                   1567: - kickEventConsumer
                   1568: {
                   1569:        [kickConsumerLock lock];
                   1570:        xpr_ev_post("kickEventConsumer (need == %d)\n",
                   1571:                needToKickEventConsumer,2,3,4,5);
                   1572:        if ( needToKickEventConsumer == YES )
                   1573:        {
                   1574:                [kickConsumerLock unlock];
                   1575:                return self;            // Request is already pending
                   1576:        }
                   1577:        needToKickEventConsumer = YES;  // Posting a request now
                   1578:        [kickConsumerLock unlock];
                   1579:        [self sendIOThreadAsyncMsg      :@selector(_performKickEventConsumer:)
                   1580:                        to              :self
                   1581:                        with            :(void *)0];
                   1582: 
                   1583:        return self;
                   1584: }
                   1585: 
                   1586: /*
                   1587:  * This is run in the I/O thread, to perform the actual message send operation.
                   1588:  * Note that we perform a non-blocking send.  The Event port in the event
                   1589:  * consumer has a queue depth of 1 message.  Once the consumer picks up that
                   1590:  * message, it runs until the event queue is exhausted before trying to read
                   1591:  * another message.  If a message is pending,there is no need to enqueue a
                   1592:  * second one.  This also keeps us from blocking the I/O thread in a msg_send
                   1593:  * which could result in a deadlock if the consumer were to make a call into
                   1594:  * the event driver.
                   1595:  */
                   1596: - _performKickEventConsumer:(id)data
                   1597: {
                   1598:        kern_return_t r;
                   1599: 
                   1600:        xpr_ev_post("_performKickEventConsumer\n", 1,2,3,4,5);
                   1601:        [kickConsumerLock lock];
                   1602:        needToKickEventConsumer = NO;   // Request received and processed
                   1603:        [kickConsumerLock unlock];
                   1604: 
                   1605:        r = msg_send( (msg_header_t *)eventMsg, SEND_TIMEOUT, 0 );
                   1606:        xpr_ev_post("_performKickEventConsumer: msg_send() == %d\n",
                   1607:                r,2,3,4,5);
                   1608:        switch ( r )
                   1609:        {
                   1610:            case SEND_TIMED_OUT:        /* Already has a message posted */
                   1611:            case SEND_SUCCESS:          /* Message is posted */
                   1612:                break;
                   1613:            default:                    /* Log the error */
                   1614:                IOLog("%s: _performKickEventConsumer msg_send returned %d\n",
                   1615:                        [self name], r);
                   1616:                break;
                   1617:        }
                   1618:        return self;
                   1619: }
                   1620: 
                   1621: /* 
                   1622:  * Event sources may need to use an I/O thread from time to time.
                   1623:  * Rather than have each instance running it's own thread, we provide
                   1624:  * a callback mechanism to let all the instances share a common Event I/O
                   1625:  * thread running in the IOTask space, and managed by the Event Driver.
                   1626:  * Returns self, or nil on error.
                   1627:  */
                   1628: - (IOReturn)sendIOThreadMsg:   (SEL)selector   // Selector to call back on
                   1629:        to              :       (id)instance    // Instance to call back
                   1630:        with            :       (id)data;       // Data to pass back
                   1631: {
                   1632:        evIoOpParams params;
                   1633: 
                   1634:        params.callback.instance = instance;
                   1635:        params.callback.selector = selector;
                   1636:        params.callback.data = data;
                   1637: 
                   1638:        return [self    _threadOpCommon : EVENT_LISTENER_CALLBACK
                   1639:                        opParams : (void *)&params
                   1640:                        async : NO];
                   1641: }
                   1642: 
                   1643: - sendIOThreadAsyncMsg:                (SEL)selector   // Selector to call back on
                   1644:        to              :       (id)instance    // Instance to call back
                   1645:        with            :       (id)data;       // Data to pass back
                   1646: {
                   1647:        evIoOpParams params;
                   1648: 
                   1649:        params.callback.instance = instance;
                   1650:        params.callback.selector = selector;
                   1651:        params.callback.data = data;
                   1652: 
                   1653:        [self   _threadOpCommon : EVENT_LISTENER_CALLBACK
                   1654:                opParams : (void *)&params
                   1655:                async : YES];
                   1656:        return self;
                   1657: }
                   1658: 
                   1659: /*
                   1660:  * This routine is run within the I/O thread, on demand from the
                   1661:  * sendIOThreadMsg::: methods above.  We attempt to dispatch a message
                   1662:  * to the specified selector and instance.
                   1663:  */
                   1664: - (IOReturn) _doPerformInIOThread:(void *)data
                   1665: {
                   1666:        IOReturn ret;
                   1667:        evCallback *msg = data;
                   1668:        if ( [msg->instance respondsTo:msg->selector] )
                   1669:        {
                   1670:            [msg->instance perform:msg->selector with:msg->data];
                   1671:            ret = IO_R_SUCCESS;
                   1672:        }
                   1673:        else
                   1674:        {
                   1675:            IOLog("%s: _doPerformInIOThread: [%s] does not respond to SEL [%s]\n",
                   1676:                        [self name],
                   1677:                        object_getClassName(msg->instance),
                   1678:                        sel_getName(msg->selector) );
                   1679:            ret = IO_R_IPC_FAILURE;
                   1680:        }
                   1681:        return ret;
                   1682: }
                   1683: 
                   1684: /*
                   1685:  * Common thread dispatch code used to drive
                   1686:  * I/O operations.  The operation to be performed is encoded
                   1687:  * in a Mach message, which we send to our I/O thread.  This
                   1688:  * thread then performs the requested operations, returning a
                   1689:  * status
                   1690:  */
                   1691: - (IOReturn)_threadOpCommon : (int)op
                   1692:                             opParams : (void *)data
                   1693:                             async : (BOOL)async
                   1694: {
                   1695:        evIoOpParams *  opParams = data;
                   1696:        evIoOpMsg opMsg;
                   1697:        kern_return_t krtn;
                   1698:        IOReturn rtn;
                   1699: #ifdef KERNEL
                   1700:        extern kern_port_t ev_port_list[];
                   1701: #endif
                   1702:        
                   1703:        xpr_ev_post("_threadOpCommon: op %d\n",op , 2,3,4,5);
                   1704:                
                   1705:        /*
                   1706:         * First, an evIoOpMsg.
                   1707:         */
                   1708:        opMsg = opMsgTemplate;
                   1709:        opMsg.header.msg_local_port = PORT_NULL;
                   1710:        
                   1711:        /*
                   1712:         * Next, the evIoOpBuf.
                   1713:         */
                   1714:        opMsg.opBuf.op = op;
                   1715:        if ( async == NO )
                   1716:        {
                   1717:            opMsg.opBuf.cmdLock = [NXConditionLock alloc];
                   1718:            [opMsg.opBuf.cmdLock initWith:CMD_INPROGRESS];
                   1719:            opMsg.opBuf.status = &rtn;
                   1720:            rtn = IO_R_INVALID_ARG;
                   1721:        }
                   1722:        opMsg.opBuf.params = *opParams;
                   1723:        
                   1724:        /*
                   1725:         * Go for it. Send the message to the I/O thread and wait for
                   1726:         * I/O complete. We use msg_send_from_kernel becuase this is called
                   1727:         * from exported methods; we could be in a user task.
                   1728:         */
                   1729: #ifdef KERNEL
                   1730:        opMsg.header.msg_remote_port = (port_t)ev_port_list[0];
                   1731:        krtn = msg_send_from_kernel(&opMsg.header, MSG_OPTION_NONE, 0);
                   1732: #else  KERNEL
                   1733:        opMsg.header.msg_remote_port = ev_port;
                   1734:        krtn = msg_send(&opMsg.header, MSG_OPTION_NONE, 0);
                   1735: #endif KERNEL
                   1736:        if(krtn) {
                   1737:                IOLog("%s: _threadOpCommon msg_send returned %d\n",
                   1738:                        [self name], krtn);
                   1739:                rtn = IO_R_IPC_FAILURE;
                   1740:                goto out;
                   1741:        }
                   1742:        if ( async == NO )
                   1743:        {
                   1744:            [opMsg.opBuf.cmdLock lockWhen:CMD_DONE];    // Wait for completion
                   1745:        }
                   1746:        else
                   1747:            rtn = IO_R_SUCCESS;
                   1748: out:
                   1749:        if ( async == NO )
                   1750:            [opMsg.opBuf.cmdLock free];
                   1751:        xpr_ev_post("_threadOpCommon: status %s\n", 
                   1752:                [self stringFromReturn:rtn], 2,3,4,5);
                   1753:        return rtn;
                   1754: }
                   1755: 
                   1756: 
                   1757: /*
                   1758:  * The following methods are executed from the I/O thread only.
                   1759:  */
                   1760: 
                   1761: /*
                   1762:  * Service incoming client evIoOp.
                   1763:  */
                   1764: - (void)_ioOpHandler   : (void *)data
                   1765: {
                   1766:        IOReturn ret;
                   1767:        evIoOpBuf *opBuf = data;
                   1768: 
                   1769:        xpr_ev_post("_ioOpHandler: op %d\n",opBuf->op, 2,3,4,5);
                   1770: 
                   1771:        if ( opBuf->status != NULL )
                   1772:            *opBuf->status = IO_R_SUCCESS;
                   1773:        switch(opBuf->op) {
                   1774:                 
                   1775:            case EVENT_LISTENER_PING:
                   1776:                /*
                   1777:                 * This is just used for the init thread to know when we've
                   1778:                 * come this far.
                   1779:                 */
                   1780:                break;
                   1781:                
                   1782:            case EVENT_LISTENER_EXIT:
                   1783:                /* 
                   1784:                 * First I/O complete this request, then terminate.
                   1785:                 */
                   1786:                [opBuf->cmdLock unlockWith:CMD_DONE];
                   1787:                IOExitThread();
                   1788: 
                   1789:            case EVENT_LISTENER_CALLBACK:
                   1790:                ret = [self _doPerformInIOThread:&(opBuf->params.callback)];
                   1791:                if ( opBuf->status != NULL )
                   1792:                    *opBuf->status = ret;
                   1793:                break;
                   1794: 
                   1795:            default:
                   1796:                IOPanic("EventDriver: Bogus opBuf.op");
                   1797:        }
                   1798:        
                   1799:        /*
                   1800:         * Release caller for synchronous operations.
                   1801:         */
                   1802:        if ( opBuf->cmdLock != nil )
                   1803:            [opBuf->cmdLock unlockWith:CMD_DONE];
                   1804: }
                   1805: 
                   1806: /*
                   1807:  * Listen for and dispatch messages for the ev and evs clients
                   1808:  * Messages received on these ports are used to control input devices, the
                   1809:  * display, and the cursor.
                   1810:  *
                   1811:  * These ports replace the old /dev/ev0 and /dev/evs0 devices.
                   1812:  * Programs which use the published event status driver API in
                   1813:  * Release 3.0 will continue to work.  Programs which directly manipulated
                   1814:  * /dev/ev0 and /dev/evs0 are out of luck.
                   1815:  *
                   1816:  * Message buffers:  The reply buffer is allocated when an RPC is generated,
                   1817:  * and is freed after we have sent the reply out.  While this may seem
                   1818:  * expensive, we normally only have between 4 and 12 RPCs in a session, with
                   1819:  * almost all occuring at WindowServer startup and login time.  IOMalloc()
                   1820:  * is fast enough to prevent any detectable delay.  The design opts to reduce
                   1821:  * wired memory at the cost of a few extra lines of code.
                   1822:  */
                   1823: static volatile void EventListener(EventDriver *inst)
                   1824: {
                   1825:        msg_header_t    *in;
                   1826:        int             in_size;
                   1827:        msg_header_t    *out;
                   1828:        int             out_size;
                   1829:        msg_return_t    r;
                   1830:        boolean_t       result;
                   1831:        boolean_t       ok = TRUE;
                   1832:        EvInMsg         in_msg;                 // Big enough for most input
                   1833:        extern boolean_t Event_server();
                   1834:        extern boolean_t EventStatus_server();
                   1835:        
                   1836:        in_size = sizeof in_msg;
                   1837:        in = &in_msg.hdr;
                   1838:        out_size = 0;
                   1839:        out = (msg_header_t *)NULL;             // Dynamically alloc as needed
                   1840: 
                   1841:        while ( ok )
                   1842:        {
                   1843:            in->msg_local_port = inst->ev_port_set;
                   1844:            in->msg_size = in_size;
                   1845:            
                   1846:            r = msg_receive( in, RCV_LARGE, 0 );
                   1847:            switch( r )
                   1848:            {
                   1849:                case RCV_SUCCESS:
                   1850:                        break;
                   1851: 
                   1852:                case RCV_TOO_LARGE:
                   1853:                        /* If we already grew it, free grown buffer */
                   1854:                        if ( in_size > (sizeof in_msg) )
                   1855:                            IOFree( (void *)in, in_size );
                   1856:                        /* Get a new buffer of an appropriate size. */
                   1857:                        in_size = in->msg_size;
                   1858:                        in = (msg_header_t *)IOMalloc( in_size );
                   1859:                        xpr_ev_post(
                   1860:                                "EventListener: msg ID %d insize %d: 0x%x\n",
                   1861:                                in->msg_id, in_size,in,4,5);
                   1862:                        continue;
                   1863: 
                   1864:                case RCV_INVALID_PORT:  /* Driver is being freed */
                   1865:                        ok = FALSE;
                   1866:                        continue;
                   1867: 
                   1868:                default:
                   1869:                        IOLog("%s: error on msg_receive (%d)\n",
                   1870:                                [inst name], r);
                   1871:                        continue;
                   1872:            }
                   1873:            xpr_ev_post("EventListener: msg ID %d size %d\n",
                   1874:                        in->msg_id, in->msg_size,3,4,5);
                   1875:            /*
                   1876:             * We have arranged for notification when the WindowServer
                   1877:             * dies.  The eventPort, owned by the WindowServer, has been
                   1878:             * checked in for port death notification.
                   1879:             * In the event of it's death, we assume that the WindowServer
                   1880:             * has met an unfortunate fate, and invoke our device close
                   1881:             * actions.
                   1882:             */
                   1883:            if ( in->msg_local_port == inst->notify_port )
                   1884:            {
                   1885:                notification_t *nmsg = (notification_t *)in;
                   1886:        
                   1887:                if ( nmsg->notify_port == inst->event_kern_port &&
                   1888:                     inst->event_kern_port!= (port_t)KERN_PORT_NULL )
                   1889:                {
                   1890:                    [inst evClose:inst->ev_port token:inst->eventPort];
                   1891: #ifdef DEBUG
                   1892:                    IOLog("%s: client token invalidated\n", [inst name]);
                   1893: #endif
                   1894:                }
                   1895:                continue;
                   1896:            }
                   1897:            /*
                   1898:             * We got a request.  If it's on the privileged ev_port, 
                   1899:             * test the message to see if it's a control message for us.
                   1900:             * If it's not a control message, try passing it to the
                   1901:             * Event_server.
                   1902:             */
                   1903:            result = FALSE;
                   1904:            switch( in->msg_id )
                   1905:            {
                   1906:                case EV_IO_OP_MSG_ID:
                   1907:                    if ( in->msg_local_port == inst->ev_port )
                   1908:                    {
                   1909:                        [inst _ioOpHandler:&((evIoOpMsg *)in)->opBuf];
                   1910:                        result = TRUE;
                   1911:                    }
                   1912:                    break;
                   1913: 
                   1914:                default:
                   1915:                    /* A real RPC needs a reply buffer.  Make one. */
                   1916:                    if ( out == (msg_header_t *)NULL )
                   1917:                    {
                   1918:                            out_size = sizeof (EvOutMsg);
                   1919:                            out = (msg_header_t *)IOMalloc( out_size );
                   1920:                            xpr_ev_post(
                   1921:                              "EventListener: msg ID %d replysize %d: 0x%x\n",
                   1922:                                        in->msg_id, out_size,out,4,5);
                   1923:                    }
                   1924:                    result = Event_server( in, out );
                   1925:                    break;
                   1926:            }
                   1927: 
                   1928:            if ( result == FALSE )
                   1929:            {
                   1930:                IOLog("%s: invalid message ID %d\n",
                   1931:                        [inst name], in->msg_id );
                   1932:            }
                   1933:            else        /* result == TRUE */
                   1934:            {
                   1935:                if(in->msg_remote_port!=PORT_NULL && out!=(msg_header_t*)NULL)
                   1936:                {
                   1937:                    /*
                   1938:                     * We were passed a reply port.  Set up and send a
                   1939:                     * reply message.  If this fails, it's because of
                   1940:                     * a MiG error.  No big deal. Just log it and try to go on.
                   1941:                     */
                   1942:                    if ( out->msg_size > out_size ) /* Mem smasher? panic? */
                   1943:                        IOLog("%s: reply msg overflow (%d > %d)\n",
                   1944:                                [inst name], out->msg_size, out_size);
                   1945:                    r = msg_send(out, MSG_OPTION_NONE, 0);
                   1946:                    xpr_ev_post("EventListener: msg ID %d reply stat %d\n",
                   1947:                                in->msg_id, r,3,4,5);
                   1948:                    if ( r != SEND_SUCCESS )
                   1949:                        IOLog("%s: error on msg_send (%d)\n",
                   1950:                                [inst name], r);
                   1951:                }
                   1952:            }
                   1953:            /*
                   1954:             * Done with messages.  Free the reply buffer, and shrink the
                   1955:             * input buffer as needed.
                   1956:             */
                   1957:            if ( out != (msg_header_t *)NULL )
                   1958:            {
                   1959:                IOFree( (void *)out, out_size );
                   1960:                out = (msg_header_t *)NULL;
                   1961:                out_size = 0;
                   1962:            }
                   1963:            if ( in_size > (sizeof in_msg) )
                   1964:            {
                   1965:                IOFree( (void *)in, in_size );
                   1966:                in_size = sizeof in_msg;
                   1967:                in = &in_msg.hdr;
                   1968:            }
                   1969:        }
                   1970: 
                   1971:        (volatile void) IOExitThread();
                   1972: }
                   1973: 
                   1974: @end
                   1975: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.