Annotation of kernel/bsd/dev/ppc/kmDevice.m, revision 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:  * 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
        !            74: const char *mach_title = "Mac OS X Server Operating System"; // Used by km.m also
        !            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 {
        !           201:                     kmDrawString( newConsole, "Starting Mac OS X Server");
        !           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.