Annotation of kernel/bsd/dev/ppc/kmDevice.m, revision 1.1.1.2

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:  * kmDevice.m - kernel keyboard/monitor module, ObjC implementation.
                     28:  *
                     29:  * HISTORY
                     30:  * 21 Sep 92   Joe Pasqua
                     31:  *     Created i386 version based on m88k version.
                     32:  */
                     33:  
                     34: #import <driverkit/generalFuncs.h>
                     35: #import <machkit/NXLock.h>
                     36: #import <driverkit/ppc/driverTypesPrivate.h>
                     37: #import <driverkit/kernelDriver.h>
                     38: #import <bsd/sys/types.h>
                     39: #import <bsd/sys/tty.h>
                     40: #import <bsd/dev/ppc/cons.h>
                     41: #import <bsd/sys/conf.h>
                     42: #import <bsd/sys/fcntl.h>
                     43: #import <bsd/sys/errno.h>
                     44: #import <bsd/sys/msgbuf.h>
                     45: #import <bsd/dev/ppc/FBConsole.h>
                     46: #import <bsd/dev/ppc/SerialConsole.h>
                     47: #import <bsd/dev/ppc/kmDevice.h>
                     48: #import <bsd/dev/kmreg_com.h>
                     49: #import <bsd/sys/reboot.h>
                     50: #import <kernserv/prototypes.h>
                     51: #import <driverkit/IODisplay.h>
                     52: #import <driverkit/IOFrameBufferDisplay.h>
                     53: #import <driverkit/IODisplayPrivate.h>
                     54: #import <driverkit/IOConfigTable.h>
                     55: #import <bsd/dev/ppc/kmWaitCursor.h>
                     56: #import <bsd/sys/proc.h>
                     57: #import <bsd/sys/systm.h>
                     58: 
                     59: #import <kern/assert.h>
                     60: #import <machdep/ppc/boot.h>
                     61: 
                     62: #import "PCKeyboardDefs.h"
                     63: #import "PPCKeyboardPriv.h"
                     64: #import "ConsoleSupport.h"
                     65: #import "km.h"
                     66: 
                     67: IODisplayInfo  bootDisplayInfo;
                     68: 
                     69: static IOConsoleInfo *serialConsole;
                     70: static int bootGraphicsMode = NO;
                     71: static short prettyShutdown = 0;
                     72: 
                     73: // Title strings for the various windows
1.1.1.2 ! root       74: const char *mach_title = "Darwin Operating System"; // Used by km.m also
1.1       root       75: static const char *alert_title  = "Alert";
                     76: 
                     77: 
                     78: #if    KERNOBJC
                     79: // Module Globals
                     80: static int kmUnit;     // Incremented to keep track of what unit we're on
                     81: static id display;
                     82:        // display == nil means that we do not have a display object around
                     83:        // yet. In this case we use the basicConsole. When display != nil
                     84:        // we can use it's console support mechanism to do our displaying.
                     85: 
                     86: // The following function pointers are used by DoAlert and DoRestore. They
                     87: // get called at interrupt level and can't execute ObjC code. To avoid doing
                     88: // so we bind the lock and unlock methods that are used and call them thru
                     89: // these pointers.
                     90: static id (*lockProc)(), (*unlockProc)();
                     91: 
                     92: #define        AllocConsole()          \
                     93:                AllocDisplayConsole(display) 
                     94: 
                     95: LANG_TYPE glLanguage;
                     96: 
                     97: #else
                     98: 
                     99: #define        AllocConsole()          basicConsole
                    100: 
                    101: #endif KERNOBJC
                    102: 
                    103: 
                    104: static IOConsoleInfo * 
                    105: AllocDisplayConsole( id display )
                    106: {
                    107: IOConsoleInfo * consoleInfo = NULL;
                    108: 
                    109:     if( display)
                    110:        consoleInfo = [display allocateConsoleInfo];
                    111:     if( NULL == consoleInfo)
                    112:        consoleInfo = basicConsole;
                    113:     return( consoleInfo);
                    114: }
                    115: 
                    116: 
                    117: // Used for putting up alert panels very early, before kmId is valid.
                    118: IOConsoleInfo *kmAlertConsole;
                    119: 
                    120: /*
                    121:  * Calculate incremented index for inBuf.
                    122:  */
                    123: static inline int
                    124: inbuf_incr(int x)
                    125: {
                    126:        if(++x == INBUF_SIZE) {
                    127:                return 0;
                    128:        }
                    129:        else {
                    130:                return x;
                    131:        }
                    132: }
                    133: 
                    134: /*
                    135:  * Initialize the console enough for printf's to work via kmputc. No 
                    136:  * text window will be created if booting in icon mode. Keyboard is 
                    137:  * not enabled. 
                    138:  */
                    139: 
                    140: void
                    141: initialize_screen(void * args)
                    142: {
                    143:     extern int initialized;
                    144:     Boot_Video * framebufferArgs = (Boot_Video *) args;
                    145: 
                    146:     cons.t_dev = makedev(12, 0); /* point the cons device to cdevsw's km dev */
                    147: 
                    148:     serialConsole = SerialAllocateConsole();
                    149: 
                    150:     if( framebufferArgs->v_baseAddr) {
                    151:        /*
                    152:        * Initialize the OpenFirmware based framebuffer console.
                    153:        */
                    154:        static char * ofPixelEncoding = "PPPPPPPP";
                    155: 
                    156:        bzero(&bootDisplayInfo, sizeof(bootDisplayInfo));
                    157:        bootDisplayInfo.width                   = framebufferArgs->v_width;
                    158:        bootDisplayInfo.height                  = framebufferArgs->v_height;
                    159:        bootDisplayInfo.totalWidth              = framebufferArgs->v_rowBytes;
                    160:        bootDisplayInfo.rowBytes                = framebufferArgs->v_rowBytes;
                    161:        bootDisplayInfo.refreshRate             = 75;           // very approx
                    162:        bootDisplayInfo.frameBuffer             = (void *)framebufferArgs->v_baseAddr;
                    163:        bootDisplayInfo.bitsPerPixel            = IO_8BitsPerPixel;
                    164:        bootDisplayInfo.colorSpace              = IO_RGBColorSpace;
                    165:        strcpy( bootDisplayInfo.pixelEncoding, ofPixelEncoding);
                    166:        basicConsole = BasicAllocateConsole(&bootDisplayInfo);
                    167:     }
                    168:     if( basicConsole == NULL)
                    169:        basicConsole = serialConsole;
                    170: 
                    171:     if( framebufferArgs->v_display & 1)
                    172:        bootGraphicsMode = YES;
                    173: 
                    174:     basicConsoleMode = bootGraphicsMode ? SCM_GRAPHIC : SCM_TEXT;
                    175:     (*basicConsole->Init)(
                    176:        basicConsole, basicConsoleMode, (bootGraphicsMode == NO), (bootGraphicsMode == NO), mach_title);
                    177: 
                    178:     initialized = TRUE;
                    179: }
                    180: 
                    181: #if    KERNOBJC
                    182: 
                    183: @implementation kmDevice
                    184: 
                    185: - (void)registerDisplay:newDisplay
                    186: {
                    187:     IOConsoleInfo *    newConsole;
                    188: 
                    189:     if (display == nil) {
                    190:        display = newDisplay;
                    191: 
                    192:        if( NO == probed) {
                    193:            newConsole = AllocDisplayConsole( newDisplay);
                    194:            if( newConsole) {
                    195:                (*newConsole->Init)(
                    196:                    newConsole, fbMode, YES, fbMode == SCM_TEXT, mach_title);
                    197:                 fbp[FB_DEV_NORMAL] = newConsole;
                    198:                if( fbMode == SCM_TEXT)
                    199:                    kmdumplog();
                    200:                else {
1.1.1.2 ! root      201:                     kmDrawString( newConsole, "Starting Darwin OS");
1.1       root      202:                     [self animationCtl: KM_ANIM_RESUME];
                    203:                }
                    204:            }
                    205:             newConsole = AllocDisplayConsole( newDisplay);
                    206:            if( newConsole)
                    207:                 fbp[FB_DEV_ALERT] = newConsole;
                    208: 
                    209:        } else {
                    210:            // somebody like the window server has changed modes,
                    211:            // but we still own the display!
                    212:            fbMode = SCM_OTHER;
                    213:             [self animationCtl: KM_ANIM_STOP];
                    214: 
                    215:             fbp[FB_DEV_NORMAL] = AllocDisplayConsole( newDisplay);
                    216:             fbp[FB_DEV_ALERT] = AllocDisplayConsole( newDisplay);
                    217:        }
                    218:     }
                    219: }
                    220: 
                    221: - (void)unregisterDisplay:oldDisplay
                    222: {
                    223:     if (display == oldDisplay) {
                    224:         [self animationCtl: KM_ANIM_SUSPEND];
                    225:        basicConsole = serialConsole;
                    226:         display = nil;
                    227: 
                    228:         if( fbp[FB_DEV_NORMAL])
                    229:             (*fbp[FB_DEV_NORMAL]->Free) (fbp[FB_DEV_NORMAL]);
                    230:         if( fbp[FB_DEV_ALERT])
                    231:             (*fbp[FB_DEV_ALERT]->Free) (fbp[FB_DEV_ALERT]);
                    232: 
                    233:         fbp[FB_DEV_NORMAL] = serialConsole;
                    234:         fbp[FB_DEV_ALERT] = serialConsole;
                    235:     }
                    236: }
                    237: 
                    238: 
                    239: /* Probe routine for a pseudo-device driver. */
                    240: + (BOOL)probe : deviceDescription
                    241: {
                    242:     // Proceed with keyboard initialization.
                    243: 
                    244:     if ([kmId init:YES fb_mode: 
                    245:            bootGraphicsMode ? SCM_GRAPHIC : SCM_TEXT] == nil)
                    246:     {
                    247:        IOLog("kmDevice: continuing with bad kmDevice instance\n");
                    248:        [kmId free];
                    249:        kmId = nil;
                    250:        return NO;
                    251:     } else
                    252:        kmId->probed = YES;
                    253: 
                    254:     return YES;
                    255: }
                    256: 
                    257: + (IODeviceStyle)deviceStyle
                    258: {
                    259:     return IO_PseudoDevice;
                    260: }
                    261: 
                    262: /* 
                    263:  * Can't put this in the kmDevice object because we might need it
                    264:  * before kmId is initialized.
                    265:  */
                    266: static int kmDeviceAnimationState = -1;
                    267: static simple_lock_data_t kmDeviceAnimationLock;
                    268: 
                    269: /*
                    270:  * Create a kmDevice. This should only be called once in the lifetime of 
                    271:  * the system. It can be called from kmDevice's probe:, or from km.m's
                    272:  * alert() (if alert is called before IOTask autoconf).
                    273:  */
                    274: + new
                    275: {
                    276:        char            name[20];
                    277:        kmDevice        *km_id;
                    278:        int i;
                    279:        
                    280:         simple_lock_init(&kmDeviceAnimationLock);
                    281: 
                    282:        km_id = [self alloc];
                    283:        km_id->kmOpenLock = [NXLock new];
                    284:        (IMP)lockProc = [km_id->kmOpenLock methodFor:@selector(lock)];
                    285:        (IMP)unlockProc = [km_id->kmOpenLock methodFor:@selector(unlock)];
                    286:        km_id->kbId = nil;
                    287:        
                    288:        for(i=0; i<NUM_FB_DEVS; i++) {
                    289:                km_id->fbp[i] = NULL;
                    290:        }
                    291:        
                    292:        /*
                    293:         * Global kmId is id of first kmDevice created.
                    294:         */
                    295:        if(kmUnit == 0) {
                    296:                ASSERT(kmId == nil);
                    297:                kmId = km_id;
                    298:        }
                    299:        
                    300:        /*
                    301:         * Special case for this one, it's hard coded - there is always 
                    302:         * at least one of these, and it's created before autoconf.
                    303:         */
                    304:         km_id->fbp[FB_DEV_NORMAL] = basicConsole;
                    305:         km_id->fbp[FB_DEV_ALERT] = basicConsole;
                    306:        [kmId setUnit:kmUnit];
                    307:        sprintf(name, "kmDevice%d", kmUnit++);  
                    308:        [kmId setName:name];
                    309:        [kmId setDeviceKind:"kmDevice"];
                    310:        [kmId setLocation:NULL];
                    311:        return km_id;
                    312: }
                    313: 
                    314: /*
                    315:  * Reusable initialization method. kmOpenLock must already have been 
                    316:  * initialized. initKb enables initialiation of keyboard.
                    317:  */
                    318: - init : (BOOL)initKb
                    319:         fb_mode : (ScreenMode)fb_mode
                    320: {
                    321:        id              rtn = self;
                    322:        
                    323:        [kmOpenLock lock];
                    324:        
                    325:        /*
                    326:         * Init local instance variables.
                    327:         */
                    328:        inDex = outDex  = 0;
                    329:        blockIn         = 0;
                    330:        alertRefCount   = 0;
                    331:        fbMode          = fb_mode;
                    332:        simple_lock_init(&inBufLock);
                    333:        
                    334:        if(initKb) {
                    335:                /*
                    336:                 * connect to Keyboard.
                    337:                 */
                    338:                if([self initKb] == nil) {
                    339:                        IOLog("kmDevice: No Keyboard Found\n");
                    340:                        /* but continue anyway... */
                    341:                }
                    342:        }
                    343:        [super init];
                    344:        if( (!hasRegistered) && initKb) {
                    345:                [self registerDevice];
                    346:                hasRegistered = YES;
                    347:        }
                    348: 
                    349:        [kmOpenLock unlock];
                    350:        return rtn;
                    351: }
                    352: 
                    353: - initKb
                    354: // Description:        Initialize connection with PCKeyboard object
                    355: {
                    356:        IOReturn drtn;
                    357:        
                    358:        drtn = IOGetObjectForDeviceName("PPCKeyboard0", &kbId);
                    359:        if(drtn) {
                    360:                IOLog("km init: Can't find PPCKeyboard0 (%s)\n",
                    361:                        [self stringFromReturn:drtn]);
                    362:                return nil;
                    363:        }
                    364:        
                    365:        drtn = [kbId becomeOwner:self];
                    366:        if(drtn) {
                    367:                IOLog("km init: becomeOwner failed (%s)\n",
                    368:                        [self stringFromReturn:drtn]);
                    369:                return nil;
                    370:        }
                    371:        
                    372:        /*
                    373:         * Also register to be notified if anyone else relinquishes
                    374:         * ownership after we give it up. This allows us to take over
                    375:         * the frame buffer and keyboard when the window server exits.
                    376:         */
                    377:        drtn = [kbId desireOwnership:self];
                    378:        if(drtn) {
                    379:                IOLog("km init: desireOwnership failed (%s)\n",
                    380:                        [self stringFromReturn:drtn]);
                    381:                return nil;
                    382:        }
                    383:        return self;
                    384: }
                    385: 
                    386: /*
                    387:  * Interface to bsd code.
                    388:  */
                    389: - (int)kmOpen : (int)flag
                    390: {
                    391:        int rtn = 0;
                    392: 
                    393:        [kmOpenLock lock];
                    394:        if(flag & ( O_POPUP | O_ALERT)) {
                    395:                switch(fbMode) {
                    396:                    case SCM_TEXT:
                    397:                        /*
                    398:                         * Easy case, we already have a place to do putc()'s. 
                    399:                         * Note for SCM_TEXT case, alert text just goes to 
                    400:                         * the normal console.
                    401:                         */
                    402:                        break;
                    403:                    case SCM_ALERT:
                    404:                        alertRefCount++;
                    405:                        break;
                    406: 
                    407:                    default:
                    408:                        /*
                    409:                         * Create an alert window.
                    410:                         *
                    411:                         * We only want to allow this for
                    412:                         * programs during system startup (eg.
                    413:                         * they must be run as root, and PostScript
                    414:                         * must not be running.
                    415:                         */
                    416:                        if(suser(current_proc()->p_ucred,
                    417:                                                &current_proc()->p_acflag)) {
                    418:                                rtn = EACCES;
                    419:                                goto out;
                    420:                        }
                    421:                        if(fbMode == SCM_OTHER) {
                    422:                                rtn = EBUSY;
                    423:                                goto out;
                    424:                        }
                    425: 
                    426:                        /*
                    427:                         * Dropping to single user mode => O_POPUP,
                    428:                         * so make the console text mode.
                    429:                         */
                    430:                        if( flag & O_POPUP) {
                    431:                            fbMode = SCM_TEXT;
                    432:                            (*fbp[FB_DEV_NORMAL]->Init)(
                    433:                                    fbp[FB_DEV_NORMAL], SCM_TEXT, TRUE, TRUE, mach_title );
                    434: 
                    435:                        } else {
                    436:                           /*
                    437:                            * Jump into "alert mode". Note that alertRefCount
                    438:                            * doesn't get decremented in close; the user has
                    439:                            * to do an explicit KMIOCRESTORE.
                    440:                            */
                    441:                            alertRefCount++;
                    442:                            savedFbMode = fbMode;
                    443:                            fbMode = SCM_ALERT;
                    444:                            (*fbp[FB_DEV_ALERT]->Init)(
                    445:                                    fbp[FB_DEV_ALERT], fbMode, TRUE, TRUE, alert_title );
                    446:                        }
                    447:                }
                    448:        }
                    449:        
                    450:        /*
                    451:         * km.m takes care of Unix-y tty stuff.
                    452:         */
                    453: out:
                    454:        [kmOpenLock unlock];
                    455:        return rtn;
                    456: }
                    457: 
                    458: - (int)kmPutc : (int)c
                    459: {
                    460:        switch(fbMode) {
                    461:            case SCM_TEXT:
                    462:                (*fbp[FB_DEV_NORMAL]->PutC)(fbp[FB_DEV_NORMAL], c);
                    463:                return 0;
                    464:                
                    465:            case SCM_ALERT:
                    466:                ASSERT(fbp[FB_DEV_ALERT] != NULL);
                    467:                (*fbp[FB_DEV_ALERT]->PutC)(fbp[FB_DEV_ALERT], c);
                    468:                return 0;
                    469: 
                    470:            default:
                    471:                /*
                    472:                 * No place to put this text. This is not an error.
                    473:                 */
                    474:                return 0;
                    475:        }
                    476: }
                    477: 
                    478: /*
                    479:  * Blocking read routine. This assumes that interrupts and threads are 
                    480:  * working, since keyboard driver will need that functionality...OK?
                    481:  */
                    482: 
                    483: - (int)kmGetc
                    484: {
                    485:        int c;
                    486:        
                    487:        simple_lock(&inBufLock);
                    488:        blockIn = 1;
                    489:        while(inDex == outDex) {
                    490:                /*
                    491:                 * Just wait for something to show up...
                    492:                 */
                    493:                thread_sleep((void *)inBuf, &inBufLock, TRUE);
                    494:                simple_lock(&inBufLock);
                    495:        } 
                    496:        c = inBuf[outDex];
                    497:        outDex = inbuf_incr(outDex);
                    498:        blockIn = 0;
                    499:        simple_unlock(&inBufLock);
                    500:        return c;
                    501: }
                    502: 
                    503: #endif //KERNOBJC
                    504: 
                    505: /*
                    506:  * ioctl equivalents. All return an errno.
                    507:  */
                    508:  
                    509: /*
                    510:  * Client finished with alert panel. Called from ioctl and from inside the 
                    511:  * kernel via alert_done().
                    512:  */
                    513: int DoRestore(void)
                    514: {
                    515:        int rtn = 0;
                    516: 
                    517: #if    KERNOBJC
                    518:        
                    519:        if (kmAlertConsole) {   // No kmDevice yet!
                    520:            (*kmAlertConsole->Restore)(kmAlertConsole);
                    521:            (*kmAlertConsole->Free)(kmAlertConsole);
                    522:            kmAlertConsole = NULL;
                    523:            return 0;
                    524:        }
                    525:        
                    526:        if (kmId == nil)
                    527:            return 0;
                    528: 
                    529: 
                    530:        /*
                    531:         * Have to protect with kmOpenLock since we may alter frame buffer
                    532:         * context.
                    533:         */
                    534:        (*lockProc)(kmId->kmOpenLock, @selector(lock));
                    535:        if(kmId->fbMode == SCM_ALERT) {
                    536:                if(kmId->alertRefCount == 0) {
                    537:                        /*
                    538:                         * No can do. I'm not sure when this could 
                    539:                         * ever happen...
                    540:                         */
                    541:                        rtn = EBUSY;
                    542:                        goto out;
                    543:                }
                    544:                if(--kmId->alertRefCount != 0) {
                    545:                
                    546:                        /*
                    547:                         * Not out of the woods yet, other user(s) of alert
                    548:                         * panel still active. 
                    549:                         */
                    550:                        goto out;
                    551:                }
                    552:                
                    553:                /*
                    554:                 * Last user of alert/popup window.
                    555:                 */
                    556:                kmId->fbMode = kmId->savedFbMode;
                    557:                if(kmId->fbMode != SCM_ALERT) {
                    558:                        rtn = (*kmId->fbp[FB_DEV_ALERT]->Restore)(
                    559:                            kmId->fbp[FB_DEV_ALERT]);
                    560:                }
                    561:                else {
                    562:                        IOLog("kmDevice: Recursive SCM_ALERT in restore!\n");
                    563:                }
                    564:                goto out;
                    565:        } else {
                    566:                /*
                    567:                 * Not in alert mode, this is a nop (and it's also somewhat
                    568:                 * unexpected...).
                    569:                 */
                    570:                rtn = EINVAL;
                    571:        }
                    572: out:
                    573:        (*unlockProc)(kmId->kmOpenLock, @selector(unlock));
                    574: 
                    575: #endif // KERNOBJC
                    576: 
                    577:        return rtn;
                    578: }
                    579: 
                    580: #if    KERNOBJC
                    581: 
                    582: - (int)restore
                    583: {
                    584:     return DoRestore();
                    585: }
                    586: 
                    587: - (int)drawRect : (const struct km_drawrect *)kmRect
                    588: {
                    589:        struct km_drawrect rect = *kmRect;
                    590:        int size, ret;
                    591:        
                    592:        if(fbMode != SCM_GRAPHIC) {
                    593:                /*
                    594:                 * No can do.
                    595:                 */
                    596:                return EBUSY;
                    597:        }
                    598:        /*
                    599:         * Copy in user data so the console DrawRect routine
                    600:         * doesn't have to.
                    601:         */
                    602: 
                    603:         if( (rect.x & 3) == 3) {
                    604:             size = rect.width * rect.height;           // size in bytes, 8bit src
                    605: 
                    606:        } else {
                    607:        rect.width = (rect.width + 3) & ~3;     // Round up to 4 pixel boundary
                    608:        size = (rect.width >> 2) * rect.height; // size in bytes
                    609:        }
                    610:        rect.data.bits = (unsigned char *)kalloc( size );
                    611:        if (copyin(kmRect->data.bits, rect.data.bits, size)) {
                    612:            ret = -1;
                    613:            goto out;
                    614:        }
                    615: 
                    616:        ret = (*fbp[FB_DEV_NORMAL]->DrawRect)(fbp[FB_DEV_NORMAL], &rect);
                    617: 
                    618: out:
                    619:        kfree( rect.data.bits, size );
                    620:        return ret;
                    621: }
                    622: 
                    623: - (int)eraseRect : (const struct km_drawrect *)kmRect
                    624: {
                    625:         if(fbMode != SCM_GRAPHIC) {
                    626:                /*
                    627:                 * No can do.
                    628:                 */
                    629:                return EBUSY;
                    630:        }
                    631:        return (*fbp[FB_DEV_NORMAL]->EraseRect)(fbp[FB_DEV_NORMAL], kmRect);
                    632: }
                    633: 
                    634: - (int)disableCons
                    635: {
                    636:        /*
                    637:         * This means that tty code has detected a "console 
                    638:         * now invalid" situation.
                    639:         */
                    640: #if 0
                    641:        if(fbMode == SCM_TEXT) {
                    642:                fbMode = SCM_OTHER;
                    643:        }
                    644: #endif
                    645:        return 0;
                    646: }
                    647: 
                    648: #endif // KERNOBJC
                    649: 
                    650: static void
                    651: kmDeviceDrawCursor()
                    652: {
                    653:     IOConsoleInfo *device;
                    654:     
                    655:     simple_lock(&kmDeviceAnimationLock);
                    656: 
                    657:     if (kmDeviceAnimationState > 0) {
                    658:        device = kmId->fbp[FB_DEV_NORMAL];
                    659:        if (device && (kmId->fbMode == SCM_GRAPHIC)) {
                    660:            (void)(*device->DrawRect)(device,
                    661:                &kmDeviceWaitCursor[kmDeviceAnimationState - 1]);
                    662:        }
                    663:        if (++kmDeviceAnimationState > KM_DEVICE_WAITCURSOR_NSTATES)
                    664:            kmDeviceAnimationState = 1;
                    665:        ns_timeout((func)kmDeviceDrawCursor, 0, KM_DEVICE_WAITCURSOR_DELAY, 
                    666:                        CALLOUT_PRI_THREAD);
                    667:     }
                    668:     simple_unlock(&kmDeviceAnimationLock);
                    669: }
                    670: 
                    671: /* Called once and only once from main(),
                    672:  */
                    673: void
                    674: kmEnableAnimation(void)
                    675: {
                    676:     if( kmId == nil) {
                    677:        kmId = [kmDevice new];
                    678:        [kmId init:NO fb_mode: 
                    679:                bootGraphicsMode ? SCM_GRAPHIC : SCM_TEXT];
                    680:     }
                    681:     [kmId animationCtl:KM_ANIM_RESUME];
                    682: }
                    683: 
                    684: void
                    685: kmDisableAnimation(void)
                    686: {
                    687:     if (kmId != nil)
                    688:        [kmId animationCtl:KM_ANIM_STOP];
                    689: }
                    690: 
                    691: #if    KERNOBJC
                    692: 
                    693: - (int)animationCtl : (km_anim_ctl_t)ctl
                    694: {
                    695:        int doAnimation = 0;
                    696:        int ret = 0;
                    697:        
                    698:        if (fbMode != SCM_GRAPHIC)
                    699:            return 0;
                    700:            
                    701:        simple_lock(&kmDeviceAnimationLock);
                    702:        switch(ctl) {
                    703:            case KM_ANIM_STOP:
                    704:            case KM_ANIM_SUSPEND:
                    705:                if (kmDeviceAnimationState > 0) {
                    706:                    kmDeviceAnimationState = -kmDeviceAnimationState;
                    707:                    (void)(*fbp[FB_DEV_NORMAL]->DrawRect)
                    708:                        (fbp[FB_DEV_NORMAL], &kmDeviceBlankCursor);
                    709:                }
                    710:                 ns_untimeout((func)kmDeviceDrawCursor, 0);
                    711:                 if( ctl == KM_ANIM_STOP)
                    712:                     kmDeviceAnimationState = 0;
                    713:                break;
                    714:            case KM_ANIM_RESUME:
                    715:                if (kmDeviceAnimationState < 0) {
                    716:                    kmDeviceAnimationState = -kmDeviceAnimationState;
                    717:                    doAnimation = 1;
                    718:                }
                    719:                break;
                    720:            default:
                    721:                ret = EINVAL;
                    722:                break;
                    723:        }
                    724:        simple_unlock(&kmDeviceAnimationLock);
                    725:        if (doAnimation)
                    726:            kmDeviceDrawCursor();
                    727:        return ret;
                    728: }
                    729: 
                    730: - (int)getStatus : (unsigned *)statusp
                    731: {
                    732:        unsigned status = KMS_SEE_MSGS;
                    733:        
                    734:        if(fbMode == SCM_GRAPHIC) {
                    735:            status = 0;
                    736:        }
                    737:        *statusp = status;
                    738:        return 0;
                    739: }
                    740: 
                    741: - (int)getScreenSize : (struct ConsoleSize *)size
                    742: {
                    743:        if (fbp[FB_DEV_NORMAL] == 0)
                    744:            return EINVAL;
                    745:        
                    746:        (*fbp[FB_DEV_NORMAL]->GetSize)(fbp[FB_DEV_NORMAL], size);
                    747:        return 0;
                    748: }
                    749: 
                    750: #endif KERNOBJC
                    751: 
                    752: #import <bsd/dev/ppc/keycodes.h>
                    753: 
                    754: int ProcessKbdEvent(PCKeyboardEvent *ke)
                    755: {
                    756:     // State of the modifier keys:
                    757:     static boolean_t   control_left, control_right,
                    758:                        shift_left, shift_right, caps_lock,
                    759:                        alt_left, alt_right,
                    760:                        cmd_left, cmd_right;
                    761:     boolean_t valid, shift, control, cmd, c;
                    762: 
                    763:     valid = FALSE;
                    764:     switch (ke->keyCode) {
                    765:        case ADBK_CONTROL:
                    766:            control_left = ke->goingDown;
                    767:            break;
                    768: 
                    769:        case ADBK_CONTROL_R:
                    770:            control_right = ke->goingDown;
                    771:            break;
                    772:            
                    773:        case ADBK_SHIFT:
                    774:            shift_left = ke->goingDown;
                    775:            break;
                    776: 
                    777:        case ADBK_SHIFT_R:
                    778:            shift_right = ke->goingDown;
                    779:            break;
                    780: 
                    781:        case ADBK_CAPSLOCK:
                    782:            caps_lock = ke->goingDown;
                    783:            break;
                    784:        
                    785:        case ADBK_OPTION:
                    786:            alt_left = ke->goingDown;
                    787:            break;
                    788:            
                    789:        case ADBK_OPTION_R:
                    790:            alt_right = ke->goingDown;
                    791:            break;
                    792: 
                    793:        case ADBK_FLOWER:
                    794:            cmd_left = ke->goingDown;
                    795:            break;
                    796: 
                    797:        default:
                    798:            valid = TRUE;
                    799:     }
                    800: 
                    801:     if (!valid)
                    802:         return inv;
                    803: 
                    804:     // caps lock is just a pain at this point
                    805:     shift = shift_right || shift_left;  // || caps_lock;
                    806: 
                    807:     control = (control_left || control_right) ? (_N_KEYCODES * 2) : 0;
                    808:     c = keycodeToAscii[((ke->keyCode << 1) | shift) + control];
                    809: 
                    810:    cmd = (cmd_right || cmd_left) ? 0x80 : 0;
                    811: 
                    812:     switch (c) {
                    813:        case dim:
                    814:        case bright:
                    815:        case loud:
                    816:        case quiet:
                    817:        case up:
                    818:        case down:
                    819:            break;
                    820:     
                    821:        default:
                    822:            c |= cmd;
                    823:            break;
                    824:     }
                    825: 
                    826: //printf("{raw:%lx, ascii:%lx}",ke->keyCode,c);
                    827: 
                    828:     if (!ke->goingDown)        // Ignore keys coming up
                    829:        return(inv);
                    830:     return(c);
                    831: }
                    832: 
                    833: #if    KERNOBJC
                    834: 
                    835: - (void)dispatchKeyboardEvent:(PCKeyboardEvent *)event;
                    836: // Description:        Called when the keyboard object receives a new keyboard
                    837: //             Event. Don't free the event object.
                    838: {
                    839:     register int c;
                    840: 
                    841:     if ((c = ProcessKbdEvent(event)) == inv)
                    842:        return;
                    843: 
                    844:     // Normal ASCII data. pass it up.
                    845:     if(blockIn) {
                    846:            //
                    847:            // We're in 'blocking input' mode; add this to 
                    848:            // the input buffer if there is room.
                    849:            //
                    850:            simple_lock(&inBufLock);
                    851:            if(inbuf_incr(inDex) == outDex) {
                    852:                    //
                    853:                    // Overflow. Oh well.
                    854:                    //
                    855:                    simple_unlock(&inBufLock);
                    856:                    return;
                    857:            }
                    858:            inBuf[inDex] = c;
                    859:            inDex = inbuf_incr(inDex);
                    860:            thread_wakeup((void *)inBuf);
                    861:            simple_unlock(&inBufLock);
                    862:     }
                    863:     else {
                    864:            //
                    865:            // Normal console input.
                    866:            //
                    867:            struct tty *tp = &cons;
                    868: 
                    869:            (*linesw[tp->t_line].l_rint) (c, tp);
                    870:     }
                    871:     return;
                    872: }
                    873: 
                    874: #else
                    875: 
                    876: void
                    877: cDispatchKeyboardEvent(PCKeyboardEvent *event)
                    878: {
                    879:     register int c;
                    880:     struct tty *tp = &cons;
                    881: 
                    882:     if ((c = ProcessKbdEvent(event)) == inv)
                    883:        return;
                    884: #if 0
                    885:     cnputc(c);
                    886: #else
                    887:     (*linesw[tp->t_line].l_rint) (c, tp);
                    888: #endif
                    889: 
                    890:     return;
                    891: }
                    892: 
                    893: #endif KERNOBJC
                    894: 
                    895: #if    KERNOBJC
                    896: 
                    897: /*
                    898:  * ev driver (or DPS or ...) is taking over the screen and keyboard. 
                    899:  * This should always succeed.
                    900:  */
                    901: - (IOReturn)relinquishOwnershipRequest : device
                    902: {
                    903:         [self animationCtl: KM_ANIM_STOP];
                    904: 
                    905:        fbMode = SCM_OTHER;
                    906:        /*
                    907:         * FIXME - notify parent of SCM_UNINIT.
                    908:         */
                    909:        return IO_R_SUCCESS;
                    910: }
                    911: 
                    912: /*
                    913:  * Called when ev/DPS, which has been the owner of Keyboard, relinquishes 
                    914:  * ownership. I think this means that we unconditionally go to SCM_TEXT 
                    915:  * mode...
                    916:  */
                    917: 
                    918: static char *k_languages[L_NUM_LANGUAGE] = {
                    919:        "English",
                    920:        "French",
                    921:        "German",
                    922:        "Spanish",
                    923:        "Italian",
                    924:        "Swedish",
                    925:        "Japanese", 
                    926:        };
                    927: 
                    928: 
                    929: - (IOReturn)canBecomeOwner : device
                    930: {
                    931:        IOReturn drtn;
                    932:        static short checkedSystemConfig = 0;
                    933:        static short preventPrettyShutdown = 0;
                    934:        
                    935:        /*
                    936:         * Regain control of keyboard.
                    937:         */
                    938:        if((drtn = [kbId becomeOwner:self])) {
                    939:            IOLog("km canBecomeOwner: becomeOwner failed (%s)\n",
                    940:                    [self stringFromReturn:drtn]);
                    941:            /*
                    942:             * But continue, although we have no keyboard...
                    943:             */
                    944:        }
                    945: 
                    946:        if (!checkedSystemConfig) {
                    947:            IOConfigTable       *configTable;
                    948:            const char          *val;
                    949:            
                    950:            checkedSystemConfig = 1;
                    951:            configTable = [IOConfigTable newFromSystemConfig];
                    952:            val = [configTable valueForStringKey:"Shutdown Graphics"];
                    953:            if (val) {
                    954:                if (!strcmp(val,"No"))
                    955:                    preventPrettyShutdown = 1;
                    956:                [IOConfigTable freeString:val];
                    957:            }
                    958: 
                    959:            val = [configTable valueForStringKey:"Language"];
                    960:            if (val) {
                    961:                int             i;
                    962:                
                    963:                for (i=0; i<L_NUM_LANGUAGE; i++) {
                    964:                    if (!strcmp(val, k_languages[i])) {
                    965:                        glLanguage = i;
                    966:                        break;
                    967:                    }
                    968:                }
                    969:                [IOConfigTable freeString:val];
                    970:            }
                    971: 
                    972:            [configTable free];
                    973:        }
                    974: 
                    975:        if (preventPrettyShutdown)
                    976:            prettyShutdown = 0;
                    977:        
                    978:        if (prettyShutdown)
                    979:            fbMode = SCM_GRAPHIC;
                    980:        else
                    981:            fbMode = SCM_TEXT;
                    982:            
                    983:        (*fbp[FB_DEV_NORMAL]->Init)(
                    984:            fbp[FB_DEV_NORMAL], fbMode, TRUE, TRUE, mach_title);
                    985: 
                    986:         if (prettyShutdown) {
                    987:             [self drawGraphicPanel: KM_PANEL_NS];
                    988: 
                    989:             switch(prettyShutdown) {
                    990:             case 1:
                    991:                 [self graphicPanelString: "Restarting the computer...\n"];
                    992:                 break;
                    993:             case 2:
                    994:                 [self graphicPanelString: "Shutting down the computer...\n"];
                    995:                 break;
                    996:             default:
                    997:                 [self graphicPanelString: "Please wait..."];
                    998:            }
                    999: 
                   1000:             kmDeviceAnimationState = -1;
                   1001:             [self animationCtl: KM_ANIM_RESUME];
                   1002:        }
                   1003: 
                   1004:        return IO_R_SUCCESS;
                   1005: }
                   1006: 
                   1007: #endif // KERNOBJC
                   1008: 
                   1009: /*
                   1010:  * Kernel internal alert panel support.
                   1011:  */
                   1012: 
                   1013: void DoSafeAlert(const char *windowTitle, const char *msg, boolean_t saveUnder )
                   1014: {
                   1015: #if    KERNOBJC
                   1016:     if (kmId == nil)
                   1017: #endif
                   1018:     {
                   1019:        // We haven't created a kmDevice yet! We can't put up a panel or
                   1020:        // call ObjC stuff.  Create an alert console.
                   1021: #if    KERNOBJC
                   1022:        if (kmAlertConsole)
                   1023:            return;
                   1024: #endif
                   1025:        // ...unless we already have basicConsole in a text mode.
                   1026:        if (basicConsoleMode == SCM_ALERT ||
                   1027:            basicConsoleMode == SCM_TEXT) {
                   1028:                if (basicConsole)
                   1029:                    while (*msg)
                   1030:                        (basicConsole->PutC)(basicConsole, *msg++);
                   1031:                return;
                   1032:        }
                   1033:        kmAlertConsole = basicConsole;
                   1034:        if (kmAlertConsole) {
                   1035:            (*kmAlertConsole->Init)(
                   1036:                kmAlertConsole, SCM_ALERT, FALSE, TRUE, windowTitle);
                   1037:            while(*msg)
                   1038:                (kmAlertConsole->PutC)(kmAlertConsole, *msg++);
                   1039:        }
                   1040:        return;
                   1041:     }
                   1042: 
                   1043: #if    KERNOBJC
                   1044:     /* 
                   1045:      * Create alert panel if necessary
                   1046:      */
                   1047:     (*lockProc)(kmId->kmOpenLock, @selector(lock));
                   1048:     switch(kmId->fbMode) {
                   1049:        case SCM_TEXT:
                   1050:            /*
                   1051:             * Easy case, we already have a place to do putc()'s. 
                   1052:             * Note for SCM_TEXT case, alert text just goes to 
                   1053:             * the normal console.
                   1054:             */
                   1055:            break;
                   1056: 
                   1057:        /*
                   1058:         * FIXME - maybe do a case for SCM_UNINIT, do allow printfs
                   1059:         * via alert() very early in boot.
                   1060:         */             
                   1061:        default:
                   1062:            /*
                   1063:             * Jump into "alert mode". 
                   1064:             */
                   1065: 
                   1066:             kmId->savedFbMode = kmId->fbMode;
                   1067:             kmId->fbMode = SCM_ALERT;
                   1068: 
                   1069:             /*
                   1070:             * Create an alert window.
                   1071:             */
                   1072:             (*kmId->fbp[FB_DEV_ALERT]->Init)(
                   1073:                 kmId->fbp[FB_DEV_ALERT], SCM_ALERT, saveUnder, TRUE, windowTitle);
                   1074: 
                   1075:            /* fall through */
                   1076: 
                   1077:        case SCM_ALERT:
                   1078:            kmId->alertRefCount++;
                   1079:            break;
                   1080:     }
                   1081:     (*unlockProc)(kmId->kmOpenLock, @selector(unlock));
                   1082:     
                   1083:     /*
                   1084:      * Print alert message.
                   1085:      */
                   1086:     {
                   1087:     IOConsoleInfo *cons;
                   1088:     
                   1089:        if (kmId->fbMode == SCM_ALERT)
                   1090:            cons = kmId->fbp[FB_DEV_ALERT];
                   1091:        else
                   1092:            cons = kmId->fbp[FB_DEV_NORMAL];
                   1093:        while(*msg)
                   1094:            (*cons->PutC)(cons, *msg++);
                   1095:     }
                   1096: #endif // KERNOBJC
                   1097: 
                   1098:     return;
                   1099: }
                   1100: 
                   1101: extern int scc_getc(int unit, int line, boolean_t wait, boolean_t raw);
                   1102: extern PCKeyboardEvent * PPCStealKeyEvent();
                   1103: 
                   1104: // This gets called from interrupt level by kdp
                   1105: 
                   1106: int kmtrygetc()
                   1107: {
                   1108:     int c = -1;
                   1109:     PCKeyboardEvent * event;
                   1110: 
                   1111:     event = PPCStealKeyEvent();
                   1112:     if(event)
                   1113:        c = ProcessKbdEvent(event);
                   1114: 
                   1115:     if( (c != -1) && ( c != inv)) {
                   1116:        return(c);
                   1117:     } else {
                   1118: /* modem port is 1, printer port is 0 */
                   1119: #define LINE   1
                   1120:        return( scc_getc(0 /* ignored */, LINE, 0, 0));
                   1121:     }
                   1122: }
                   1123: 
                   1124: void DoAlert(const char *windowTitle, const char *msg)
                   1125: {
                   1126:     DoSafeAlert(windowTitle, msg, TRUE);
                   1127: }
                   1128: 
                   1129: #if    KERNOBJC
                   1130: 
                   1131: - (void)doAlert        : (const char *)windowTitle
                   1132:                   msg : (const char *)msg
                   1133: {
                   1134:        DoSafeAlert(windowTitle, msg, TRUE);
                   1135: }
                   1136: 
                   1137: 
                   1138: - (IOReturn)setIntValues               : (unsigned *)parameterArray
                   1139:                           forParameter : (IOParameterName)parameterName
                   1140:                                  count : (unsigned)count
                   1141: {
                   1142:        if(!strcmp(parameterName, "prettyShutdown"))
                   1143:        {
                   1144:                prettyShutdown = (short)(*parameterArray);
                   1145:                return IO_R_SUCCESS;
                   1146:        }
                   1147:        else
                   1148:        { 
                   1149:        /* Pass parameters we don't recognize to our superclass. */
                   1150:         return [super setIntValues:parameterArray
                   1151:                forParameter:parameterName count:count];
                   1152:        }
                   1153: }
                   1154: 
                   1155: @end
                   1156: 
                   1157: #endif // KERNOBJC
                   1158: 
                   1159: /* end of kmDevice.m */
                   1160: 
                   1161: 

unix.superglobalmegacorp.com

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