Annotation of kernel/bsd/dev/ppc/PPCKeyboard.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: 
                     25: /*     Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved. 
                     26:  *
                     27:  * PPCKeyboard.m - Keyboard driver.
                     28:  * 
                     29:  *
                     30:  * HISTORY
                     31:  * 11-Aug-92    Joe Pasqua at NeXT
                     32:  *      Created. 
                     33:  * 8-April-97   Simon Douglas
                     34:  *      Munged into ADB version. Remove mouse interface.
                     35:  */
                     36:  
                     37: // TO DO:
                     38: //   Make this an indirect client of ADB. ADB should probe to create multiple
                     39: //   event sources.
                     40: // Notes:
                     41: // * To find things that need to be fixed, search for FIX, to find questions
                     42: //   to be resolved, search for ASK, to find stuff that still needs to be
                     43: //   done, search for TO DO.
                     44: 
                     45: #define MACH_USER_API  1
                     46: #undef KERNEL_PRIVATE
                     47: 
                     48: #import <machkit/NXLock.h>
                     49: #import <driverkit/IODevice.h>
                     50: #import <driverkit/driverServer.h>
                     51: #import <driverkit/generalFuncs.h>
                     52: #import <driverkit/interruptMsg.h>
                     53: #import <bsd/dev/ppc/PPCKeyboardPriv.h>
                     54: #import <bsd/dev/ppc/PPCKeyboard.h>
                     55: #import <bsd/dev/ppc/PCKeyboardDefs.h>
                     56: #import <driverkit/ppc/directDevice.h>
                     57: #import <driverkit/ppc/driverTypes.h>
                     58: #import <bsd/dev/ev_types.h>
                     59: #import <bsd/dev/event.h>
                     60: 
                     61: #import <kern/thread_call.h>
                     62: 
                     63: #include <mach_kdb.h>
                     64: #include <mach/mach_types.h>
                     65: #include <sys/tty.h>
                     66: #include <sys/conf.h>
                     67: #include <machdep/ppc/mach_param.h>
                     68: #include <machine/machspl.h>
                     69: 
                     70: #include <machdep/ppc/powermac.h>
                     71: 
                     72: #include "busses.h"
                     73: #include "adb.h"
                     74: #import  "IOADBBus.h"
                     75: 
                     76: unsigned char  extendCount;
                     77: 
                     78: static int adbAsyncAvail = FALSE;                      /* can try async ADB */
                     79: static int keyboard_led_state;      /* state of caps/num/scroll lock */
                     80: static id  adb_driver;              // pointer to adb indirect driver
                     81: 
                     82: extern struct tty   cons;
                     83: 
                     84: void keyboard_updown(unsigned char key);
                     85: void keyboard_adbhandler(int number, unsigned char *buffer, int count, void * ssp);
                     86: void keyboard_init(void);
                     87: void keyboard_updown(unsigned char key);
                     88: 
                     89: io_return_t keyboard_set_led_state(int state);
                     90: int     keyboard_get_led_state(void);
                     91: void        keyboard_initialize_led_state(void);
                     92: 
                     93: boolean_t   keyboard_initted = FALSE;
                     94: int     keyboard_adb_addr = -1;
                     95: 
                     96: #define        KeyboardIPL     3
                     97: #define        SAFE_IPL        (KeyboardIPL + 1)
                     98: 
                     99: #define MAX_PENDING_EVENTS 10
                    100: 
                    101: #if    KERNOBJC
                    102: static PPCKeyboard *_kbdObj;
                    103: #endif KERNOBJC
                    104: 
                    105: static PCKeyboardEvent _pendingEvents[MAX_PENDING_EVENTS];
                    106: static int _eventIndex;
                    107: /* Forward declarations */
                    108: static inline PCKeyboardEvent *PPCScancodeToKeyEvent( unsigned char key);
                    109: static void EnqueueKey(int keyCode, ns_time_t stamp);
                    110: 
                    111: 
                    112: /* Forward declarations */
                    113: #define msg_printf null_printf
                    114: #define msg1_printf null_printf
                    115: 
                    116: #define busywait(x)    delay(x)
                    117: 
                    118: 
                    119: //
                    120: // BEGIN:      Definitions used to keep track of key state
                    121: //
                    122: // NOTES:      Key up/down state is tracked in a bit list.  Bits are set
                    123: //             for key-down, and cleared for key-up.  The bit vector and
                    124: //             macros for it's manipulation are defined here.
                    125: #define KBV_BITS_PER_UNIT      32
                    126: #define KBV_BITS_MASK          31
                    127: #define KBV_BITS_SHIFT         5       // 1<<5 == 32, for cheap divide
                    128: #define KBV_NUNITS ((128 + (KBV_BITS_PER_UNIT-1))/KBV_BITS_PER_UNIT)
                    129: 
                    130: #define KBV_KEYDOWN(n, bits) \
                    131:        (bits)[((n)>>KBV_BITS_SHIFT)] |= (1 << ((n) & KBV_BITS_MASK))
                    132: 
                    133: #define KBV_KEYUP(n, bits) \
                    134:        (bits)[((n)>>KBV_BITS_SHIFT)] &= ~(1 << ((n) & KBV_BITS_MASK))
                    135: 
                    136: #define KBV_IS_KEYDOWN(n, bits) \
                    137:        (((bits)[((n)>>KBV_BITS_SHIFT)] & (1 << ((n) & KBV_BITS_MASK))) != 0)
                    138: 
                    139: static unsigned long   _kbdBitVector[KBV_NUNITS];
                    140: //
                    141: // END:                Definitions used to keep track of key state
                    142: //
                    143: 
                    144: 
                    145: #if    KERNOBJC
                    146: 
                    147: @implementation PPCKeyboard
                    148: + (IODeviceStyle) deviceStyle
                    149: {
                    150:   return IO_IndirectDevice;
                    151: }
                    152: 
                    153: static Protocol *protocols[] = {
                    154:       @protocol(ADBprotocol),
                    155:       nil
                    156: };
                    157: 
                    158: + (Protocol **)requiredProtocols
                    159: {
                    160:       return protocols;
                    161: }
                    162: 
                    163: 
                    164: 
                    165: #endif
                    166: 
                    167: //
                    168: // BEGIN:      Impl. of internal methods for dealing w/ kbd controller
                    169: // NOTE:       The following are utility procedures for dealing with
                    170: //             The keyboard controller. They are called from the low
                    171: //             level interrupt handler. Because of this, they can not be
                    172: //             ObjC methods.
                    173: //
                    174: 
                    175: 
                    176: static void ADBKeyboardInit(void);
                    177: 
                    178: static void
                    179: ADBKeyboardInit(void)
                    180: {
                    181:        extern boolean_t adb_initted; //extern from adb.m
                    182:     int              i;
                    183:     IOADBDeviceInfo  table[IO_ADB_MAX_DEVICE];
                    184: 
                    185:     if (!keyboard_initted) {
                    186:                //if early debugging mode, table[] is filled with trash, ADB not initialized
                    187:                if (!adb_initted) //set in adb.m if ADB were instantiated
                    188:                {
                    189:                keyboard_initted = FALSE;
                    190:                        return;
                    191:                }
                    192:        [adb_driver GetTable: table: &i];
                    193:        for (i = 0; i < ADB_DEVICE_COUNT; i++) {
                    194:                        if ((table[i].flags & ADB_FLAGS_PRESENT) == 0) 
                    195:                        {
                    196:                                continue;
                    197:                        }
                    198:                        if (table[i].originalAddress == ADB_DEV_KEYBOARD) {
                    199:                        /* Find the first ADB keyboard device, and use that. */
                    200:                                keyboard_adb_addr = i;
                    201:                                break;  //break out of for loop
                    202:                        }
                    203:        }
                    204:         keyboard_initted = TRUE;
                    205:         /* Pickup all keyboard devices */
                    206:        [adb_driver adb_register_handler:ADB_DEV_KEYBOARD: keyboard_adbhandler];
                    207:     }
                    208: }
                    209: 
                    210: 
                    211: /* Called the first time the console is opened, can't be done
                    212:  * above since it's too early
                    213:  */
                    214: void
                    215: keyboard_initialize_led_state(void)
                    216: {
                    217:     keyboard_led_state = keyboard_get_led_state();
                    218: }
                    219: 
                    220: int
                    221: keyboard_get_led_state(void)
                    222: {
                    223:     unsigned short  lights = 0;
                    224:     unsigned char   buffer[8];
                    225:     int             length;
                    226: 
                    227:     if (keyboard_adb_addr == -1)
                    228:         return 0;
                    229: 
                    230:     [adb_driver readADBDeviceRegister: keyboard_adb_addr: 2: buffer: &length];
                    231: 
                    232:     lights = buffer[0] << 8;
                    233:     if (length > 1) {
                    234:         lights |= buffer[1];
                    235:     }
                    236: 
                    237:     return ~lights;
                    238: }
                    239:     
                    240: int
                    241: keyboard_set_led_state(int lights)
                    242: {
                    243:     unsigned char buffer[2];
                    244: 
                    245:     if (keyboard_adb_addr == -1)
                    246:         return D_NO_SUCH_DEVICE;
                    247: 
                    248:     /* Inverse things for ADB */
                    249:     lights = ~lights;
                    250:     buffer[0] = lights >> 8;
                    251:     buffer[1] = lights & 0xFF;
                    252: 
                    253:     [adb_driver writeADBDeviceRegister: keyboard_adb_addr: 2: buffer: 2];
                    254: 
                    255:     return D_SUCCESS;
                    256: }
                    257: 
                    258: 
                    259: #import <kern/kdp_internal.h>
                    260: #import <mach/exception.h>
                    261: 
                    262: void 
                    263: keyboard_adbhandler(int number, unsigned char *buffer, int count, void * ssp)
                    264: {
                    265: ns_time_t      stamp;
                    266: 
                    267:     if ( (HasPMU() &&
                    268:        (buffer[0] == ADBK_POWER2 || buffer[1] == ADBK_POWER2)) ||
                    269:          (!HasPMU() &&
                    270:        (buffer[0] == ADBK_POWER && buffer[1] == ADBK_POWER)) )
                    271:     {
                    272:        if (KBV_IS_KEYDOWN(ADBK_CONTROL, _kbdBitVector))
                    273:        {
                    274:            IOGetTimestamp(&stamp);
                    275: 
                    276:            if (KBV_IS_KEYDOWN(ADBK_OPTION, _kbdBitVector))
                    277:            {
                    278:                mini_mon("", "Kernel Debugger",ssp);
                    279:                EnqueueKey(ADBK_OPTION, stamp);
                    280:            }
                    281:            else {
                    282:                if( kdp.is_conn) {
                    283: #if 0
                    284:                    kdp_raise_exception( EXC_SOFTWARE, 0, 0, ssp);
                    285: #else
                    286:                    call_kdp();
                    287: #endif
                    288:                } else {
                    289:                    mini_mon("restart", "Restart",ssp);
                    290:                }
                    291:            }
                    292:            EnqueueKey(ADBK_CONTROL, stamp);
                    293:            return;
                    294:        }
                    295:        keyboard_updown(ADBK_POWER);
                    296:        keyboard_updown(ADBK_KEYUP(ADBK_POWER));
                    297:        return;
                    298:     }
                    299: 
                    300:     keyboard_updown(buffer[0]);
                    301:     if (buffer[1] != 0xff)
                    302:         keyboard_updown(buffer[1]);
                    303: }
                    304: 
                    305: 
                    306: #if    KERNOBJC
                    307: void
                    308: KeyboardCallout()
                    309: {
                    310:        [_kbdObj interruptHandler];   
                    311: }
                    312: #else
                    313: void   cDispatchKeyboardEvent( PCKeyboardEvent *event);
                    314: #endif KERNOBJC
                    315: 
                    316: void
                    317: keyboard_updown(unsigned char key)
                    318: {
                    319:     PCKeyboardEvent *event;
                    320:     if ( (event = (PCKeyboardEvent *)PPCScancodeToKeyEvent(key)) )
                    321:     {
                    322:        // Add this event to the queue. If there is no room in the queue,
                    323:        // we toss the event. TO DO: when we fill the last entry in the
                    324:        // queue we should disable keyboard interrupts until the queue gets
                    325:        // some free space.
                    326:        if (_eventIndex == MAX_PENDING_EVENTS)
                    327:            return;
                    328:        _pendingEvents[_eventIndex++] = *event;
                    329: 
                    330:         // This call causes an interrupt message to be sent. Note that
                    331:        // if a previous message is outstanding, this call does nothing.
                    332:        // That is, no new message is queued.
                    333: 
                    334:        if( adbAsyncAvail)
                    335:        {
                    336: 
                    337: #if    KERNOBJC
                    338: #if    DRVRKITINTS
                    339:            IOSendInterrupt(identity, state, IO_DEVICE_INTERRUPT_MSG);
                    340: #else
                    341:            thread_call_func((thread_call_func_t)KeyboardCallout, 0, TRUE);
                    342: #endif DRVRKITINTS
                    343: 
                    344: #else
                    345:            cDispatchKeyboardEvent( event );
                    346:            _eventIndex = 0;
                    347: #endif DRIVERKIT
                    348:        }
                    349:    }
                    350: }
                    351: 
                    352: //
                    353: // END:                Impl. of internal methods for dealing w/ kbd controller
                    354: //
                    355: 
                    356: //
                    357: // BEGIN:      Implementation of internal functions and methods
                    358: //
                    359: static void EnqueueKey(int keyCode, ns_time_t stamp)
                    360: // Description:        Enqueue an event that corresponds to a key coming up
                    361: {
                    362:     PCKeyboardEvent event;
                    363:     
                    364:     if (_eventIndex != MAX_PENDING_EVENTS)
                    365:     {
                    366:        event.keyCode = keyCode;
                    367:        event.goingDown = 0;
                    368:        event.timeStamp = stamp;
                    369:        _pendingEvents[_eventIndex++] = event;
                    370:     }
                    371: }
                    372: 
                    373: static inline
                    374: PCKeyboardEvent *PPCScancodeToKeyEvent(
                    375:     unsigned char key)
                    376: // Description: Take a scan code from the keyboard and package it up into
                    377: //             a PCKeyboard event.
                    378: {
                    379:     static PCKeyboardEvent event;
                    380: 
                    381:     event.keyCode = ADBK_KEYVAL(key);
                    382:     IOGetTimestamp(&event.timeStamp);
                    383:     event.goingDown = ADBK_PRESS(key);
                    384: 
                    385:     if (event.goingDown)
                    386:     {
                    387:         if (KBV_IS_KEYDOWN(event.keyCode, _kbdBitVector))
                    388:             return (PCKeyboardEvent *)0;
                    389:        else
                    390:            KBV_KEYDOWN(event.keyCode, _kbdBitVector);
                    391:     }
                    392:     else
                    393:         KBV_KEYUP(event.keyCode, _kbdBitVector);
                    394: 
                    395:     return (&event);
                    396: }
                    397: 
                    398: #if    KERNOBJC
                    399: 
                    400: - (void)interruptHandler
                    401: // Description:        This method is invoked by the I/O Thread when a keyboard
                    402: //             interrupt message has been recieved. This method reads
                    403: //             the keycode, processes it into a PCKeyboardEvent and
                    404: //             sends it to our owner.
                    405: {
                    406:     int oldIPL, nEvents, i;
                    407:     PCKeyboardEvent events[MAX_PENDING_EVENTS];
                    408: 
                    409:     if (_owner == nil)
                    410:     {
                    411:         _eventIndex = 0;  //bug 2228585
                    412:         return;                // After all that, no one is interested!
                    413:        }
                    414: 
                    415:     // Safely copy the events from the pending queue
                    416:     oldIPL = spltty();
                    417:     if (_eventIndex == 1)
                    418:         events[0] = _pendingEvents[0];
                    419:     else
                    420:        bcopy(_pendingEvents, events, sizeof(PCKeyboardEvent) * _eventIndex);
                    421:     nEvents = _eventIndex;
                    422:     _eventIndex = 0;
                    423:     (void)splx(oldIPL);
                    424:     
                    425:     for (i = 0; i < nEvents; i++)
                    426:     {
                    427:        [_owner dispatchKeyboardEvent:&events[i]];
                    428:     }
                    429: }
                    430: 
                    431: #ifdef DRVRKITINTS
                    432: 
                    433: static volatile void kbdThread(PPCKeyboard *_kbdObject)
                    434: // Description: This is the function which is executed as the I/O Thread.
                    435: //             It waits for messages from driverkit and dispatches them
                    436: //             as appropriate.
                    437: {
                    438:     kern_return_t      result;
                    439:     msg_header_t       msg, *msgPtr = &msg;
                    440:     
                    441:     /* For the time being;it is already init to false */
                    442: 
                    443:     //
                    444:     // Main loop. Wait for incoming messages, dispatch as appropriate.
                    445:     //
                    446:     while (TRUE) {
                    447:        msgPtr->msg_size = sizeof(msg);
                    448:        msgPtr->msg_local_port = [_kbdObject interruptPort];
                    449:        
                    450:        result = msg_receive(msgPtr, MSG_OPTION_NONE, 0);
                    451:        if (result != RCV_SUCCESS) {
                    452:            IOLog("kbdThread: msg_receive() returned %d\n", result);
                    453:            continue;
                    454:        }
                    455:        
                    456:        if (msgPtr->msg_id == IO_DEVICE_INTERRUPT_MSG)
                    457:        {
                    458:            [_kbdObject interruptHandler];   
                    459:        } else
                    460:                        IOLog("kbdThread: non intr msg received %d\n", result);
                    461:     }
                    462: }
                    463: 
                    464: #endif DRVRKITINTS
                    465: 
                    466: - (BOOL)kbdInit:(IODeviceDescription *)deviceDescription
                    467: // Description:        Initialize the keyboard object. Returns NO on error.
                    468: {
                    469:     char           locationStr[ 24 ];
                    470:     IOADBDeviceInfo deviceInfo;
                    471: 
                    472:     _owner = nil;
                    473:     _desiredOwner = nil;
                    474:     _ownerLock = [NXLock new];
                    475: 
                    476: #ifdef DRVRKITINTS
                    477:     [self enableAllInterrupts];
                    478:     IOForkThread((IOThreadFunc)kbdThread, self);
                    479: #else
                    480:     _kbdObj = self;
                    481: #endif DRVRKITINTS
                    482: 
                    483:     ADBKeyboardInit();
                    484:     adbAsyncAvail = TRUE;
                    485: 
                    486:     interfaceId = NX_EVS_DEVICE_INTERFACE_ADB;
                    487: 
                    488:     [adb_driver getADBInfo: keyboard_adb_addr: &deviceInfo];
                    489:     handlerId = 16 + (deviceInfo.handlerID);
                    490: 
                    491:     sprintf( locationStr, "handlerID %d", handlerId);
                    492:     [self setLocation:locationStr];
                    493: 
                    494:     return YES;        
                    495: }
                    496: 
                    497: //
                    498: // END:                Implementation of internal functions and methods
                    499: //
                    500: 
                    501: //
                    502: // BEGIN:      EXPORTED PPCKeyboard methods
                    503: //
                    504: + (BOOL)probe:deviceDescription
                    505: // Description:        Bring a new instance into existance.
                    506: {
                    507:     PPCKeyboard *inst;
                    508: 
                    509:     //
                    510:     // Create an instance and initialize some basic instance variables.
                    511:     //
                    512:     inst = [[self alloc] initFromDeviceDescription:deviceDescription];
                    513: 
                    514:     [inst setUnit: 0];
                    515:     [inst setName:"PPCKeyboard0"];
                    516:     [inst setDeviceKind:"PPCKeyboard"];
                    517: 
                    518:     //
                    519:     // Proceed with initialization.
                    520:     //
                    521:     if ([inst kbdInit:deviceDescription] == NO) {
                    522:        IOLog("PPCKeyboard probe: kdbInit failed\n");
                    523:        [inst free];
                    524:        return NO;
                    525:     }
                    526:     else
                    527:        [inst registerDevice];
                    528: 
                    529:     //IODelay(1000000);
                    530: 
                    531:     [inst setAlphaLockFeedback:NO];
                    532: 
                    533:     return YES;
                    534: }
                    535: 
                    536: - initFromDeviceDescription:(IODeviceDescription *)deviceDescription
                    537: {
                    538:     
                    539:     adb_driver = [deviceDescription directDevice];
                    540:     
                    541:     return self;
                    542: }
                    543: 
                    544: - (BOOL) getHandler:(IOPPCInterruptHandler *)handler
                    545:               level:(unsigned int *) ipl
                    546:           argument:(unsigned int *) arg
                    547:        forInterrupt:(unsigned int) localInterrupt
                    548: {
                    549: #ifdef DRVRKITINTS
                    550:     *handler = KbdIntHandler;
                    551:     *ipl = 3;
                    552:     *arg = 0xdeadbeef;
                    553:     return YES;
                    554: #endif DRVRKITINTS
                    555:     return NO;
                    556: }
                    557: 
                    558: - free
                    559: // Description:        Frees an instance.
                    560: {
                    561:     [_ownerLock free];
                    562:     return [super free];
                    563: }
                    564: 
                    565: 
                    566: - (int)interfaceId
                    567: // Description:       return keyboard interface ID.
                    568: {
                    569:     return interfaceId;
                    570: }
                    571: 
                    572: - (int)handlerId
                    573: // Description:       return keyboard handler ID.
                    574: {
                    575:     return handlerId;
                    576: }
                    577: 
                    578: - (void)setAlphaLockFeedback:(BOOL)locked
                    579: // Description:        Set the keyboard LEDs to indicate the state of alpha lock
                    580: {
                    581:     keyboard_set_led_state( locked ? ADBKS_LED_CAPSLOCK : 0 );
                    582: }
                    583: 
                    584: #endif KERNOBJC
                    585: 
                    586: static PCKeyboardEvent stolenEvent;
                    587: 
                    588: PCKeyboardEvent *PPCStealKeyEvent()
                    589: // Description:        Call this routine to steal a keyboard event directly
                    590: //             from the hardware. Must be called from interrupt level.
                    591: {
                    592:     ADBKeyboardInit();
                    593: 
                    594:     if (_eventIndex == 0) {
                    595:        CheckADBPoll();
                    596:        if (_eventIndex == 0)
                    597:            return NULL;
                    598:     }
                    599:     // This sucks.
                    600:     stolenEvent = _pendingEvents[0];
                    601:     _eventIndex--;
                    602:     bcopy( &_pendingEvents[1], &_pendingEvents[0], sizeof(PCKeyboardEvent) * _eventIndex);
                    603: 
                    604:     return( &stolenEvent );
                    605: }
                    606: 
                    607: //
                    608: // END:                EXPORTED PPCKeyboard methods
                    609: //
                    610: 
                    611: #if    KERNOBJC
                    612: 
                    613: //
                    614: // BEGIN:      Implementation of the PCKeyboardExported protocol
                    615: //
                    616: - (IOReturn)becomeOwner                : client;
                    617: // Description:        Register for event dispatch via device-specific protocol.
                    618: //             (See the dispatchKeyboardEvent method)
                    619: //             Returns IO_R_SUCCESS if successful, else IO_R_BUSY. The
                    620: //             relinquishOwnershipRequest: method may be called on another
                    621: //             client during the execution of this method.
                    622: {
                    623:     IOReturn rtn;
                    624:     
                    625:     [_ownerLock lock];
                    626:     if(_owner != nil) {
                    627:        if([_owner respondsTo:@selector(relinquishOwnershipRequest:)])
                    628:        {
                    629:            rtn = [_owner relinquishOwnershipRequest:self];
                    630:        }
                    631:        else {
                    632:            IOLog("%s: owner %s does not respond to "
                    633:                    "relinquishOwnershipRequest:\n",
                    634:                    [self name], [_owner name]);
                    635:            rtn = IO_R_BUSY;
                    636:        }
                    637: 
                    638:        if(rtn == IO_R_SUCCESS) {
                    639:            _owner = client;
                    640:        }
                    641:        else {
                    642:            // NEGOTIATION FAILED
                    643:        }
                    644:     }
                    645:     else {
                    646:        _owner = client;
                    647:        rtn = IO_R_SUCCESS;
                    648:     }
                    649: 
                    650:     [_ownerLock unlock];
                    651: 
                    652:     if( rtn == IO_R_SUCCESS) {
                    653:        // Send the new owner a capslock down
                    654: 
                    655:        unsigned char   read_buf[8];
                    656:        int             rcvd_length;
                    657:        int             s;
                    658: 
                    659:        [ adb_driver readADBDeviceRegister: keyboard_adb_addr: 2: read_buf: &rcvd_length];
                    660:        if( (rcvd_length == 2) &&
                    661:            (0 == (read_buf[0] & ADBKS_CAPSLOCK_short))) {
                    662:            s = spltty();
                    663:            KBV_KEYUP(ADBK_CAPSLOCK, _kbdBitVector);
                    664:            keyboard_updown(ADBK_CAPSLOCK);
                    665:            splx(s);
                    666:        }
                    667:     }
                    668:     return rtn;
                    669: }
                    670: 
                    671: - (IOReturn)relinquishOwnership        : client;
                    672: // Description:        Relinquish ownership. Returns IO_R_BUSY if caller is not
                    673: //             current owner.
                    674: {
                    675:     IOReturn rtn;
                    676:     
                    677:     [_ownerLock lock];
                    678:     if(_owner == client) {
                    679:        rtn = IO_R_SUCCESS;
                    680:        _owner = nil;
                    681:     }
                    682:     else {
                    683:        rtn = IO_R_BUSY;
                    684:     }
                    685:     [_ownerLock unlock];
                    686:     if((rtn == IO_R_SUCCESS) && 
                    687:        _desiredOwner &&
                    688:        (_desiredOwner != client)) {
                    689:            /*
                    690:             * Notify this potential client that it can take over.
                    691:             * We'll most likely be called back during this method,
                    692:             * which is why we released _ownerLock.
                    693:             */
                    694:            if([_desiredOwner respondsTo:@selector(canBecomeOwner:)]) {
                    695:                [_desiredOwner canBecomeOwner:self];
                    696:            }
                    697:            else {
                    698:                IOLog("%s: desiredOwner does not respond to "
                    699:                        "canBecomeOwner:\n", [self name]);
                    700:            }
                    701:     }
                    702:     return rtn;
                    703: }
                    704: 
                    705: 
                    706: - (IOReturn)desireOwnership    : client;
                    707: // Description:        Request notification (via canBecomeOwner:) when
                    708: //             relinquishOwnership: is called. This allows one potential
                    709: //             client to place itself "next in line" for ownership. The
                    710: //             queue is only one deep.
                    711: {
                    712:     IOReturn rtn;
                    713:     
                    714:     [_ownerLock lock];
                    715:     if(_desiredOwner && (_desiredOwner != client)) {
                    716:        rtn = IO_R_BUSY;
                    717:     }
                    718:     else {
                    719:        _desiredOwner = client;
                    720:        rtn = IO_R_SUCCESS;
                    721:     }
                    722:     [_ownerLock unlock];
                    723:     return rtn;        
                    724: }
                    725: //
                    726: // END:                Implementation of the PCKeyboardExported protocol
                    727: //
                    728: @end
                    729: 
                    730: #endif KERNOBJC
                    731: 
                    732: 
                    733: 
                    734: 

unix.superglobalmegacorp.com

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