|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: serial_console.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 7/91
30: *
31: * Console driver for serial-line based consoles.
32: */
33:
34: #include <constty.h>
35: #if NCONSTTY > 0
36: #include <bm.h>
37: #include <platforms.h>
38:
39: #include <mach_kdb.h>
40:
41: #include <machine/machspl.h> /* spl definitions */
42: #include <device/io_req.h>
43: #include <device/tty.h>
44: #include <sys/syslog.h>
45:
46: #include <chips/busses.h>
47: #include <chips/screen_defs.h>
48: #include <chips/serial_defs.h>
49:
50: #ifdef DECSTATION
51: #include <mips/prom_interface.h>
52: #define find_rconsole(p) dec_check_rcline(p)
53: #define CONSOLE_SERIAL_LINE_NO 3
54: #endif /*DECSTATION*/
55:
56: #ifdef VAXSTATION
57: #define find_rconsole(p)
58: #define cnputc ser_putc
59: #define cngetc ser_getc
60: #define cnpollc ser_pollc
61: #define cnmaygetc ser_maygetc
62: #define CONSOLE_SERIAL_LINE_NO 3
63: #endif /*VAXSTATION*/
64:
65: #ifdef FLAMINGO
66: #define CONSOLE_SERIAL_LINE_NO 3
67: #endif
68:
69: #ifndef CONSOLE_SERIAL_LINE_NO
70: #define CONSOLE_SERIAL_LINE_NO 0
71: #endif
72:
73: /* Size this as max possible number of lines in any serial chip we might use */
74: static struct tty console_tty_data[NCONSTTY];
75: struct tty *console_tty[NCONSTTY]; /* exported */
76:
77: #define DEFAULT_SPEED B9600
78: #define DEFAULT_FLAGS (TF_EVENP|TF_ODDP|TF_ECHO)
79:
80:
81: /*
82: * A machine MUST have a console. In our case
83: * things are a little complicated by the graphic
84: * display: people expect it to be their "console",
85: * but we'd like to be able to live without it.
86: * This is not to be confused with the "rconsole" thing:
87: * that just duplicates the console I/O to
88: * another place (for debugging/logging purposes).
89: *
90: * There is then another historical kludge: if
91: * there is a graphic display it is assumed that
92: * the minor "1" is the mouse, with some more
93: * magic attached to it. And again, one might like to
94: * use the serial line 1 as a regular one.
95: *
96: */
97: #define user_console 0
98:
99: int console = 0;
100:
101: int (*console_probe)() = 0,
102: (*console_param)() = 0,
103: (*console_start)() = 0,
104: (*console_putc)() = 0,
105: (*console_getc)() = 0,
106: (*console_pollc)() = 0,
107: (*console_mctl)() = 0,
108: (*console_softCAR)() = 0;
109:
110: /*
111: * Lower-level (internal) interfaces, for printf and gets
112: */
113: int cnunit = 0; /* which unit owns the 'console' */
114: int cnline = 0; /* which line of that unit */
115: int rcline = 3; /* alternate, "remote console" line */
116:
117: rcoff()
118: {
119: spl_t s = splhigh();
120: cnpollc(FALSE);
121: rcline = 0;
122: cnpollc(TRUE);
123: splx(s);
124: }
125:
126: rcputc(c)
127: {
128: if (rcline)
129: (*console_putc)( cnunit, rcline, c);
130: }
131:
132: cnputc(c)
133: {
134: #if NBM > 0
135: if (SCREEN_ISA_CONSOLE()) {
136: /* this does its own rcputc */
137: screen_blitc(SCREEN_CONS_UNIT(), c);
138: } else
139: #endif NBM > 0
140: {
141: rcputc(c);
142: (*console_putc)( cnunit, cnline, c);/* insist on a console still */
143: }
144: if (c == '\n')
145: cnputc('\r');
146: }
147:
148: cngetc()
149: {
150: return (*console_getc)( cnunit, cnline, TRUE, FALSE);
151: }
152:
153: cnpollc(bool)
154: {
155: (*console_pollc)(cnunit, bool);
156: }
157:
158:
159: /* Debugger support */
160: cnmaygetc()
161: {
162: return (*console_getc)( cnunit, cnline, FALSE, FALSE);
163: }
164:
165:
166: #if NBM > 0
167: boolean_t
168: screen_captures(line)
169: register int line;
170: {
171: return (SCREEN_ISA_CONSOLE() &&
172: ((line == SCREEN_LINE_KEYBOARD) ||
173: (line == SCREEN_LINE_POINTER)));
174: }
175: #endif
176:
177: /*
178: * Higher level (external) interface, for GP use
179: */
180:
181:
182: /*
183: * This is basically a special form of autoconf,
184: * to get printf() going before true autoconf.
185: */
186: cons_find(tube)
187: boolean_t tube;
188: {
189: static struct bus_device d;
190: register int i;
191: struct tty *tp;
192:
193: for (i = 0; i < NCONSTTY; i++)
194: console_tty[i] = &console_tty_data[i];
195: /* the hardware device will set tp->t_addr for valid ttys */
196:
197: d.unit = 0;
198:
199: if ((console_probe == 0) ||
200: ((*console_probe)(0, &d) == 0)) {
201: /* we have no console, but maybe that's ok */
202: #if defined(DECSTATION) || defined(FLAMINGO)
203: /* no, it is not */
204: dprintf("%s", "no console!\n");
205: halt();
206: #endif
207: return 0;
208: }
209:
210: /*
211: * Remote console line
212: */
213: find_rconsole(&rcline);
214:
215: /*
216: * Console always on unit 0. Fix if you need to
217: */
218: cnunit = 0;
219:
220: #if NBM > 0
221: if (tube && screen_probe(0)) {
222:
223: /* associate screen to console iff */
224: if (console == user_console)
225: screen_console = cnunit | SCREEN_CONS_ENBL;
226: cnline = SCREEN_LINE_KEYBOARD;
227:
228: /* mouse and keybd */
229: tp = console_tty[SCREEN_LINE_KEYBOARD];
230: tp->t_ispeed = B4800;
231: tp->t_ospeed = B4800;
232: tp->t_flags = TF_LITOUT|TF_EVENP|TF_ECHO|TF_XTABS|TF_CRMOD;
233: tp->t_dev = SCREEN_LINE_KEYBOARD;
234: (*console_param)(tp, SCREEN_LINE_KEYBOARD);
235:
236: tp = console_tty[SCREEN_LINE_POINTER];
237: tp->t_ispeed = B4800;
238: tp->t_ospeed = B4800;
239: tp->t_flags = TF_LITOUT|TF_ODDP;
240: tp->t_dev = SCREEN_LINE_POINTER;
241: (*console_param)(tp, SCREEN_LINE_POINTER);
242: /* console_scan will turn on carrier */
243:
244: } else {
245: #endif NBM > 0
246: /* use non-graphic console as console */
247: cnline = CONSOLE_SERIAL_LINE_NO;
248:
249: tp = console_tty[cnline];
250: tp->t_ispeed = B9600;
251: tp->t_ospeed = B9600;
252: tp->t_flags = TF_LITOUT|TF_EVENP|TF_ECHO|TF_XTABS|TF_CRMOD;
253: (*console_softCAR)(cnunit, cnline, TRUE);
254: console = cnline;
255: tp->t_dev = console;
256: (*console_param)(tp, SCREEN_LINE_OTHER);
257: #if NBM > 0
258: }
259:
260: /*
261: * Enable rconsole interrupts for KDB
262: */
263: if (tube && rcline != cnline) {
264: tp = console_tty[rcline];
265: tp->t_ispeed = B9600;
266: tp->t_ospeed = B9600;
267: tp->t_flags = TF_LITOUT|TF_EVENP|TF_ECHO|TF_XTABS|TF_CRMOD;
268: tp->t_dev = rcline;
269: (*console_softCAR)(cnunit, rcline, TRUE);
270: (*console_param)(tp, SCREEN_LINE_OTHER);
271: } else
272: rcline = 0;
273: #endif NBM > 0
274: }
275:
276: /*
277: * Open routine
278: */
279: extern int
280: cons_start(struct tty *),
281: cons_stop(struct tty *, int),
282: cons_mctl(struct tty *, int, int);
283:
284: cons_open(dev, flag, ior)
285: int dev;
286: int flag;
287: io_req_t ior;
288: {
289: register struct tty *tp;
290: register int ttyno;
291:
292: if (dev == user_console)
293: dev = console;
294:
295: ttyno = dev;
296: if (ttyno >= NCONSTTY)
297: return D_NO_SUCH_DEVICE;
298: tp = console_tty[ttyno];
299:
300: /* But was it there at probe time */
301: if (tp->t_addr == 0)
302: return D_NO_SUCH_DEVICE;
303:
304: tp->t_start = cons_start;
305: tp->t_stop = cons_stop;
306: tp->t_mctl = cons_mctl;
307:
308: #if NBM > 0
309: if (screen_captures(ttyno))
310: screen_open(SCREEN_CONS_UNIT(), ttyno==SCREEN_LINE_KEYBOARD);
311: #endif NBM > 0
312:
313: if ((tp->t_state & TS_ISOPEN) == 0) {
314: if (tp->t_ispeed == 0) {
315: tp->t_ispeed = DEFAULT_SPEED;
316: tp->t_ospeed = DEFAULT_SPEED;
317: tp->t_flags = DEFAULT_FLAGS;
318: }
319: tp->t_dev = dev;
320: (*console_param)(tp, ttyno);
321: }
322:
323: return (char_open(dev, tp, flag, ior));
324: }
325:
326:
327: /*
328: * Close routine
329: */
330: cons_close(dev, flag)
331: int dev;
332: {
333: register struct tty *tp;
334: register int ttyno;
335: spl_t s;
336:
337: if (dev == user_console)
338: dev = console;
339:
340: ttyno = dev;
341:
342: #if NBM > 0
343: if (screen_captures(ttyno))
344: screen_close(SCREEN_CONS_UNIT(), ttyno==SCREEN_LINE_KEYBOARD);
345: #endif NBM > 0
346:
347: tp = console_tty[ttyno];
348:
349: s = spltty();
350: simple_lock(&tp->t_lock);
351:
352: ttyclose(tp);
353:
354: simple_unlock(&tp->t_lock);
355: splx(s);
356: }
357:
358: cons_read(dev, ior)
359: int dev;
360: register io_req_t ior;
361: {
362: register struct tty *tp;
363: register ttyno;
364:
365: if (dev == user_console)
366: dev = console;
367:
368: ttyno = dev;
369: #if NBM > 0
370: if (SCREEN_ISA_CONSOLE() && (ttyno == SCREEN_LINE_POINTER))
371: return screen_read(SCREEN_CONS_UNIT(), ior);
372: #endif NBM > 0
373:
374: tp = console_tty[ttyno];
375: return char_read(tp, ior);
376: }
377:
378:
379: cons_write(dev, ior)
380: int dev;
381: register io_req_t ior;
382: {
383: register struct tty *tp;
384: register ttyno;
385:
386: if (dev == user_console)
387: dev = console;
388:
389: ttyno = dev;
390: #if NBM > 0
391: if (screen_captures(ttyno))
392: return screen_write(SCREEN_CONS_UNIT(), ior);
393: #endif NBM > 0
394:
395: tp = console_tty[ttyno];
396: return char_write(tp, ior);
397: }
398:
399: /*
400: * Start output on a line
401: */
402: cons_start(tp)
403: register struct tty *tp;
404: {
405: spl_t s;
406:
407: s = spltty();
408: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
409: goto out;
410:
411: if (tp->t_outq.c_cc == 0)
412: goto out;
413:
414: tp->t_state |= TS_BUSY;
415:
416: (*console_start)(tp);
417:
418: out:
419: splx(s);
420: }
421:
422: /*
423: * Stop output on a line.
424: */
425: cons_stop(tp, flag)
426: register struct tty *tp;
427: {
428: register spl_t s;
429:
430: s = spltty();
431: if (tp->t_state & TS_BUSY) {
432: if ((tp->t_state&TS_TTSTOP)==0)
433: tp->t_state |= TS_FLUSH;
434: }
435: splx(s);
436: }
437:
438:
439: /*
440: * Modem control
441: */
442: cons_mctl(
443: struct tty *tp,
444: int bits,
445: int how)
446: {
447: return (*console_mctl)(tp->t_dev, bits, how);
448: }
449:
450: /*
451: * Abnormal close
452: */
453: cons_portdeath(dev, port)
454: int dev;
455: mach_port_t port;
456: {
457: if (dev == user_console)
458: dev = console;
459: return (tty_portdeath(console_tty[dev], port));
460: }
461:
462: /*
463: * Get/Set status rotuines
464: */
465: io_return_t
466: cons_get_status(dev, flavor, data, status_count)
467: int dev;
468: dev_flavor_t flavor;
469: int * data; /* pointer to OUT array */
470: unsigned int *status_count; /* out */
471: {
472: register struct tty *tp;
473: register int ttyno;
474:
475: if (dev == user_console)
476: dev = console;
477:
478: ttyno = dev;
479:
480: #if NBM > 0
481: if (screen_captures(ttyno) &&
482: (screen_get_status(SCREEN_CONS_UNIT(),
483: flavor, data, status_count) == D_SUCCESS))
484: return D_SUCCESS;
485: #endif NBM > 0
486:
487: tp = console_tty[ttyno];
488:
489: switch (flavor) {
490: case TTY_MODEM:
491: /* Take all bits */
492: *data = (*console_mctl)(dev, -1, DMGET);
493: *status_count = 1;
494: break;
495: default:
496: return (tty_get_status(tp, flavor, data, status_count));
497: }
498: return (D_SUCCESS);
499: }
500:
501: io_return_t
502: cons_set_status(dev, flavor, data, status_count)
503: int dev;
504: dev_flavor_t flavor;
505: int * data;
506: unsigned int status_count;
507: {
508: register struct tty *tp;
509: register int ttyno;
510:
511: if (dev == user_console)
512: dev = console;
513:
514: ttyno = dev;
515:
516: #if NBM > 0
517: if (screen_captures(ttyno) &&
518: (screen_set_status(SCREEN_CONS_UNIT(),
519: flavor, data, status_count) == D_SUCCESS))
520: return D_SUCCESS;
521: #endif NBM > 0
522:
523: tp = console_tty[ttyno];
524:
525: switch (flavor) {
526: case TTY_MODEM:
527: if (status_count < TTY_MODEM_COUNT)
528: return (D_INVALID_OPERATION);
529: (void) (*console_mctl)(dev, *data, DMSET);
530: break;
531:
532: case TTY_SET_BREAK:
533: (void) (*console_mctl)(dev, TM_BRK, DMBIS);
534: break;
535:
536: case TTY_CLEAR_BREAK:
537: (void) (*console_mctl)(dev, TM_BRK, DMBIC);
538: break;
539:
540: case TTY_STATUS:
541: {
542: register int error = D_SUCCESS;
543: struct tty_status *tsp;
544:
545: /*
546: * Defend from noise. The cshell...
547: */
548: tsp = (struct tty_status *)data;
549: if ((tsp->tt_ispeed != tp->t_ispeed) ||
550: (tsp->tt_ospeed != tp->t_ospeed) ||
551: (tsp->tt_breakc != tp->t_breakc) ||
552: ((tsp->tt_flags & ~TF_HUPCLS) != tp->t_flags)) {
553:
554: error = tty_set_status(tp, flavor, data, status_count);
555: if (error == 0) {
556: spl_t s = spltty();
557: tp->t_state &= ~(TS_BUSY|TS_FLUSH);
558: (*console_param)(tp, ttyno);
559: splx(s);
560: }
561: } else
562: if (tsp->tt_flags & TF_HUPCLS)
563: tp->t_state |= TS_HUPCLS;
564: return (error);
565: }
566: default:
567: return (tty_set_status(tp, flavor, data, status_count));
568: }
569: return (D_SUCCESS);
570: }
571:
572:
573: /*
574: * A simple scheme to dispatch interrupts.
575: *
576: * This deals with the fairly common case where we get an
577: * interrupt on each rx/tx character. A more elaborate
578: * scheme [someday here too..] would handle instead many
579: * characters per interrupt, perhaps using a DMA controller
580: * or a large SILO. Note that it is also possible to simulate
581: * a DMA chip with 'pseudo-dma' code that runs directly down
582: * in the interrupt routine.
583: */
584:
585: /*
586: * We just received a character, ship it up for further processing.
587: * Arguments are the tty number for which it is meant, a flag that
588: * indicates a keyboard or mouse is potentially attached to that
589: * tty (-1 if not), the character proper stripped down to 8 bits,
590: * and an indication of any error conditions associated with the
591: * receipt of the character.
592: * We deal here with rconsole input handling and dispatching to
593: * mouse or keyboard translation routines. cons_input() does
594: * the rest.
595: */
596: #if MACH_KDB
597: int l3break = 0x10; /* dear old ^P, we miss you so bad. */
598: #endif MACH_KDB
599:
600: cons_simple_rint(ttyno, line, c, err)
601: int line;
602: int c;
603: {
604: /*
605: * Rconsole. Drop in the debugger on break or ^P.
606: * Otherwise pretend input came from keyboard.
607: */
608: if (rcline && ttyno == rcline) {
609: #if MACH_KDB
610: if ((err & CONS_ERR_BREAK) ||
611: ((c & 0x7f) == l3break))
612: return gimmeabreak();
613: #endif /* MACH_KDB */
614: ttyno = console;
615: goto process_it;
616: }
617:
618: #if NBM > 0
619: if (screen_captures(line)) {
620: if (line == SCREEN_LINE_POINTER)
621: return mouse_input(SCREEN_CONS_UNIT(), c);
622: if (line == SCREEN_LINE_KEYBOARD) {
623: c = lk201_rint(SCREEN_CONS_UNIT(), c, FALSE, FALSE);
624: if (c == -1)
625: return; /* shift or bad char */
626: }
627: }
628: #endif NBM > 0
629: process_it:
630: cons_input(ttyno, c, err);
631: }
632:
633: /*
634: * Send along a character on a tty. If we were waiting for
635: * this char to complete the open procedure do so; check
636: * for errors; if all is well proceed to ttyinput().
637: */
638: cons_input(ttyno, c, err)
639: {
640: register struct tty *tp;
641:
642: tp = console_tty[ttyno];
643:
644: if ((tp->t_state & TS_ISOPEN) == 0) {
645: tt_open_wakeup(tp);
646: return;
647: }
648: if (err) {
649: if (err & CONS_ERR_OVERRUN)
650: log(LOG_WARNING, "sl%d: silo overflow\n", ttyno);
651:
652: if (err & CONS_ERR_PARITY)
653: if (((tp->t_flags & (TF_EVENP|TF_ODDP)) == TF_EVENP)
654: || ((tp->t_flags & (TF_EVENP|TF_ODDP)) == TF_ODDP))
655: return;
656: if (err & CONS_ERR_BREAK) /* XXX autobaud XXX */
657: c = tp->t_breakc;
658: }
659: ttyinput(c, tp);
660: }
661:
662: /*
663: * Transmission of a character is complete.
664: * Return the next character or -1 if none.
665: */
666: cons_simple_tint(ttyno, all_sent)
667: boolean_t all_sent;
668: {
669: register struct tty *tp;
670:
671: tp = console_tty[ttyno];
672: if ((tp->t_addr == 0) || /* not probed --> stray */
673: (tp->t_state & TS_TTSTOP))
674: return -1;
675:
676: if (all_sent) {
677: tp->t_state &= ~TS_BUSY;
678: if (tp->t_state & TS_FLUSH)
679: tp->t_state &= ~TS_FLUSH;
680:
681: cons_start(tp);
682: }
683:
684: if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
685: return -1;
686:
687: return getc(&tp->t_outq);
688: }
689:
690:
691:
692:
693:
694: #endif /*NCONSTTY > 0*/
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.