|
|
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: * km.m - kernel keyboard/monitor module, procedural interface.
28: *
29: * HISTORY
30: * 21 Sep 92 Joe Pasqua
31: * Created i386 version based on m88k version.
32: */
33:
34: #import <driverkit/IODevice.h>
35: #import <driverkit/generalFuncs.h>
36: #import <bsd/sys/param.h>
37: #import <bsd/sys/tty.h>
38:
39: #import <bsd/dev/ppc/cons.h>
40: #import <bsd/sys/conf.h>
41: #import <sys/systm.h>
42: #import <bsd/sys/uio.h>
43: #import <bsd/sys/fcntl.h> /* for kmopen */
44: #import <bsd/sys/errno.h>
45: #import <bsd/sys/proc.h> /* for kmopen */
46: #import <bsd/sys/msgbuf.h>
47: #import <bsd/dev/kmreg_com.h>
48: #import <kern/thread_call.h>
49: #import <kern/clock.h>
50: #import <bsd/sys/time.h>
51: #import <kernserv/ns_timer.h>
52: #import <bsd/dev/ppc/kmDevice.h>
53: #import <bsd/dev/ppc/km.h>
54: #import <bsd/dev/ppc/FBConsole.h>
55: #import <bsd/dev/ppc/PPCKeyboardPriv.h>
56: #import "kernobjc.h"
57:
58: #import <kern/assert.h>
59:
60: /*
61: * 'Global' variables, shared only by this file and conf.c.
62: */
63: extern struct tty cons;
64: struct tty *km_tty[1] = { &cons };
65:
66: /*
67: * 'Global' variables, shared only by this file and kmDevice.m.
68: */
69: int initialized = 0;
70: kmDevice *kmId; // the kmDevice
71: IOConsoleInfo *basicConsole;
72: ScreenMode basicConsoleMode;
73: extern IOConsoleInfo *kmAlertConsole;
74:
75: /*
76: * Static functions.
77: */
78: static int kmoutput(struct tty *tp);
79: static void kmstart(struct tty *tp);
80:
81: #if KERNOBJC
82: #else
83: extern void KeyboardOpen(void);
84: #endif KERNOBJC
85:
86: /*
87: * cdevsw interface to km driver.
88: */
89: int
90: kmopen(
91: dev_t dev,
92: int flag,
93: int devtype,
94: struct proc *pp)
95: {
96: int rtn;
97: int unit;
98: struct tty *tp;
99: struct winsize *wp;
100: struct ConsoleSize size;
101: int ret;
102:
103: unit = minor(dev);
104: if(unit >= NUM_KM_DEVS)
105: return (ENXIO);
106:
107: #if KERNOBJC
108: if ( (rtn = [kmId kmOpen:flag]) )
109: return rtn;
110: #endif
111:
112: /*
113: * This code lifted from 68k km.c.
114: */
115: tp = (struct tty *)&cons;
116: tp->t_oproc = kmstart;
117: tp->t_param = NULL;
118: tp->t_dev = dev;
119:
120: if ( !(tp->t_state & TS_ISOPEN) ) {
121: tp->t_iflag = TTYDEF_IFLAG;
122: tp->t_oflag = TTYDEF_OFLAG;
123: tp->t_cflag = (CREAD | CS8 | CLOCAL);
124: tp->t_lflag = TTYDEF_LFLAG;
125: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
126: termioschars(&tp->t_termios);
127: ttsetwater(tp);
128: } else if ((tp->t_state & TS_XCLUDE) && pp->p_ucred->cr_uid != 0)
129: return EBUSY;
130:
131: tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */
132: ret = ((*linesw[tp->t_line].l_open)(dev, tp));
133:
134: if (ret == 0) {
135: #if KERNOBJC
136: [kmId getScreenSize:&size];
137: #else
138: (*basicConsole->GetSize)(basicConsole, &size);
139: #endif
140: wp = &tp->t_winsize;
141: wp->ws_row = size.rows;
142: wp->ws_col = size.cols;
143: wp->ws_xpixel = size.pixel_width;
144: wp->ws_ypixel = size.pixel_height;
145: }
146:
147: #if KERNOBJC
148: #else
149: KeyboardOpen();
150: #endif KERNOBJC
151:
152: return ret;
153: }
154:
155: int
156: kmclose(
157: dev_t dev,
158: int flag,
159: int mode,
160: struct proc *p)
161: {
162: /*
163: * Note we don't close possible alert window here; we have to rely on
164: * user to do a KMIOCRESTORE.
165: */
166:
167: struct tty *tp;
168:
169: tp = &cons;
170: (*linesw[tp->t_line].l_close)(tp,flag);
171: ttyclose(tp);
172: return (0);
173: }
174:
175: int
176: kmread(
177: dev_t dev,
178: struct uio *uio,
179: int ioflag)
180: {
181: register struct tty *tp;
182:
183: tp = &cons;
184: return ((*linesw[tp->t_line].l_read)(tp, uio, ioflag));
185: }
186:
187: int
188: kmwrite(
189: dev_t dev,
190: struct uio *uio,
191: int ioflag)
192: {
193: register struct tty *tp;
194:
195: tp = &cons;
196: return ((*linesw[tp->t_line].l_write)(tp, uio, ioflag));
197: }
198:
199: int
200: kmioctl(
201: dev_t dev,
202: int cmd,
203: caddr_t data,
204: int flag,
205: struct proc *p)
206: {
207: int error;
208: struct tty *tp = &cons;
209: struct ConsoleSize size;
210: struct winsize *wp;
211:
212: switch (cmd) {
213:
214: #if KERNOBJC
215: case KMIOCRESTORE:
216: return [kmId restore];
217:
218: case KMIOCDRAWRECT:
219: return [kmId drawRect:(struct km_drawrect *)data];
220:
221: case KMIOCERASERECT:
222: return [kmId eraseRect:(struct km_drawrect *)data];
223:
224: case KMIOCDISABLCONS:
225: return [kmId disableCons];
226:
227: case KMIOCANIMCTL:
228: return [kmId animationCtl:*(km_anim_ctl_t *)data];
229: case KMIOCDUMPLOG:
230: return kmdumplog();
231: #else
232: case KMIOCRESTORE:
233: case KMIOCDRAWRECT:
234: case KMIOCERASERECT:
235: case KMIOCDISABLCONS:
236: case KMIOCANIMCTL:
237: case KMIOCDUMPLOG:
238: return 0;
239: #endif //KERNOBJC
240:
241:
242: case KMIOCSTATUS:
243:
244: #if KERNOBJC
245: return [kmId getStatus:(unsigned *)data];
246: #else
247: *((unsigned *)data) = KMS_SEE_MSGS;
248: return 0;
249: #endif //KERNOBJC
250:
251: case KMIOCSIZE:
252: #if KERNOBJC
253: [kmId getScreenSize:&size];
254: #else
255: (*basicConsole->GetSize)(basicConsole, &size);
256: #endif //KERNOBJC
257: wp = (struct winsize *)data;
258: wp->ws_row = size.rows;
259: wp->ws_col = size.cols;
260: wp->ws_xpixel = size.pixel_width;
261: wp->ws_ypixel = size.pixel_height;
262: return 0;
263:
264: case TIOCSWINSZ:
265: /* Prevent changing of console size --
266: * this ensures that login doesn't revert to the
267: * termcap-defined size
268: */
269: return EINVAL;
270:
271: /* Bodge in the CLOCAL flag as the km device is always local */
272: case TIOCSETA:
273: case TIOCSETAW:
274: case TIOCSETAF: {
275: register struct termios *t = (struct termios *)data;
276: t->c_cflag |= CLOCAL;
277: /* No Break */
278: }
279: default:
280: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
281: if (error >= 0) {
282: return error;
283: }
284: error = ttioctl (tp, cmd, data, flag, p);
285: if (error >= 0) {
286: return error;
287: }
288: else {
289: return ENOTTY;
290: }
291: }
292: }
293:
294: /*
295: * this works early on, after initialize_screen() but before autoconf (and thus
296: * before we have a kmDevice).
297: */
298: int
299: kmputc(
300: dev_t dev,
301: int c)
302: {
303: IOConsoleInfo *console;
304:
305: if(kmId) {
306: /*
307: * After autoconfig, let kmDevice handle this.
308: */
309: if (c == '\n') {
310: [kmId kmPutc:'\r'];
311: }
312: return [kmId kmPutc:c];
313: }
314:
315: if( kmAlertConsole)
316: console = kmAlertConsole;
317: else {
318: console = basicConsole;
319: if( !initialized || (basicConsoleMode != SCM_TEXT))
320: return( 0);
321: }
322:
323: if(c == '\n') {
324: (*console->PutC)(console, '\r');
325: }
326: (*console->PutC)(console, c);
327: return 0;
328: }
329:
330: int
331: kmgetc(
332: dev_t dev)
333: {
334: /* in bsd/dev/ppc/cons.c */
335: extern int cnputc(char c);
336: int c;
337:
338: #if KERNOBJC
339: if(kmId == nil) {
340: return 0;
341: }
342: c = [kmId kmGetc];
343: #endif //KERNOBJC
344:
345: if (c == '\r') {
346: c = '\n';
347: }
348: cnputc(c);
349: return c;
350: }
351:
352: int
353: kmgetc_silent(
354: dev_t dev)
355: {
356: int c;
357:
358: #if KERNOBJC
359: if(kmId == nil) {
360: return 0;
361: }
362: c = [kmId kmGetc];
363: #endif //KERNOBJC
364: if (c == '\r') {
365: c = '\n';
366: }
367: return c;
368: }
369:
370: /*
371: * Callouts from linesw.
372: */
373:
374: #define KM_LOWAT_DELAY ((ns_time_t)1000)
375:
376: static void
377: kmstart(
378: struct tty *tp)
379: {
380: if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
381: goto out;
382: if (tp->t_outq.c_cc == 0)
383: goto out;
384: tp->t_state |= TS_BUSY;
385: if (tp->t_outq.c_cc > tp->t_lowat) {
386: /*
387: * Start immediately.
388: */
389: thread_call_func(
390: (thread_call_func_t) kmoutput, tp, TRUE);
391: }
392: else {
393: /*
394: * Wait a bit...
395: */
396: ns_timeout((func) kmoutput, tp, KM_LOWAT_DELAY,
397: CALLOUT_PRI_THREAD);
398: }
399: out:
400: ttwwakeup(tp);
401: }
402:
403: static int
404: kmoutput(
405: struct tty *tp)
406: {
407: /*
408: * FIXME - to be grokked...copied from m68k km.c.
409: */
410: char buf[80];
411: char *cp;
412: int cc = -1;
413:
414: while (tp->t_outq.c_cc > 0) {
415: cc = ndqb(&tp->t_outq, 0);
416: if (cc == 0)
417: break;
418: cc = min(cc, sizeof buf);
419: (void) q_to_b(&tp->t_outq, buf, cc);
420: for (cp = buf; cp < &buf[cc]; cp++) {
421:
422: #if KERNOBJC
423: [kmId kmPutc:(*cp & 0x7f)];
424: #else
425: (*basicConsole->PutC)(basicConsole, *cp & 0x7f);
426: #endif
427: }
428: }
429: if (tp->t_outq.c_cc > 0) {
430: thread_call_func(
431: (thread_call_func_t)kmoutput, tp, TRUE);
432: }
433: tp->t_state &= ~TS_BUSY;
434: ttwwakeup(tp);
435: return 0;
436: }
437:
438: /*
439: * Alert panel interface (which we'd like to do away with if at all
440: * possible).
441: */
442: int
443: kmpopup (
444: const char *title,
445: int flag,
446: int width,
447: int height,
448: boolean_t allocmem)
449: {
450:
451: DoAlert(title, "");
452: return 0;
453: }
454:
455: int
456: kmrestore()
457: {
458: DoRestore();
459: return 0;
460: }
461:
462:
463: /*
464: * Write message to console; create an alert panel if no text-type window
465: * currently exists. Caller must call alert_done() when finished.
466: * The height and width arguments are not used; they are provided for
467: * compatibility with the 68k version of alert().
468: */
469: int
470: alert(
471: int width,
472: int height,
473: const char *title,
474: const char *msg,
475: int p1,
476: int p2,
477: int p3,
478: int p4,
479: int p5,
480: int p6,
481: int p7,
482: int p8)
483: {
484: char smsg[200];
485:
486: sprintf(smsg, msg, p1, p2, p3, p4, p5, p6, p7, p8);
487: DoAlert(title, smsg);
488: return 0;
489: }
490:
491: int
492: alert_done()
493: {
494: DoRestore();
495: return 0;
496: }
497:
498: /*
499: * printf() a message to an an alert panel. Can be used any time after calling
500: * alert(). This might go away before release, let's see..
501: */
502: void
503: aprint(
504: const char *msg,
505: int p1,
506: int p2,
507: int p3,
508: int p4,
509: int p5,
510: int p6,
511: int p7,
512: int p8)
513: {
514: char smsg[200];
515: char *cp = smsg;
516:
517: ASSERT(kmId != nil);
518: sprintf(smsg, msg, p1, p2, p3, p4, p5, p6, p7, p8);
519: while(cp) {
520: kmputc(0, *cp++);
521: }
522: }
523:
524: /*
525: * Dump message log.
526: */
527: int
528: kmdumplog()
529: {
530:
531: extern struct msgbuf * msgbufp; /* defined in subr_prf.c */
532: char * mp;
533:
534: if( msgbufp->msg_magic != MSG_MAGIC)
535: return( 0);
536: mp = &msgbufp->msg_bufc[msgbufp->msg_bufx];
537: do {
538: if( *mp)
539: kmputc( 12, *mp);
540: if( ++mp >= &msgbufp->msg_bufc[MSG_BSIZE])
541: mp = msgbufp->msg_bufc;
542: } while( mp != &msgbufp->msg_bufc[msgbufp->msg_bufx]);
543: return 0;
544: }
545:
546: #if KERNOBJC
547:
548: void
549: kmDrawGraphicPanel(GraphicPanelType panelType)
550: {
551: if (kmId != nil)
552: [kmId drawGraphicPanel:panelType];
553: }
554:
555: void
556: kmGraphicPanelString(char *str)
557: {
558: if (kmId != nil)
559: [kmId graphicPanelString:str];
560: }
561:
562: #endif //KERNOBJC
563:
564:
565:
566: /* end of km.m */
567:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.