|
|
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: ¤t_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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.