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