* Copyright (c) 1992 The Regents of the University of California.
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratories.
* %sccs.include.redist.c%
* @(#)cons.c 7.2 (Berkeley) %G%
* from: $Header: cons.c,v 1.10 92/07/10 00:02:42 torek Exp $
* Console (indirect) driver.
#include "machine/bsd_openprom.h"
struct tty
*constty
= 0; /* virtual console output device */
struct tty
*fbconstty
= 0; /* tty structure for frame buffer console */
int rom_console_input
; /* when set, hardclock calls cnrom() */
int cons_ocount
; /* output byte count */
extern struct promvec
*promvec
;
* The output driver may munge the minor number in cons.t_dev.
struct tty cons
; /* rom console tty device */
static void cnstart
__P((struct tty
*));
static void cnfbstart
__P((struct tty
*));
static void cnfbstop
__P((struct tty
*, int));
static void cnfbdma
__P((void *));
register struct tty
*tp
= &cons
;
void zsconsole(), bwtwoconsole();
tp
->t_dev
= makedev(0, 0); /* /dev/console */
tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
tp
->t_param
= (int (*)(struct tty
*, struct termios
*))nullop
;
out
= *promvec
->pv_stdout
;
* Tell the keyboard driver to direct ASCII input here.
printf("unknown console input source %d; using rom\n", in
);
printf("unknown console output sink %d; using rom\n", out
);
tp
->t_stop
= (void (*)(struct tty
*, int))nullop
;
cnopen(dev
, flag
, mode
, p
)
register struct tty
*tp
= &cons
;
if ((tp
->t_state
& TS_ISOPEN
) == 0) {
tp
->t_iflag
= TTYDEF_IFLAG
;
tp
->t_oflag
= TTYDEF_OFLAG
;
tp
->t_lflag
= TTYDEF_LFLAG
;
tp
->t_cflag
= TTYDEF_CFLAG
;
tp
->t_state
= TS_ISOPEN
| TS_CARR_ON
;
} else if (tp
->t_state
& TS_XCLUDE
&& p
->p_ucred
->cr_uid
!= 0)
return ((*linesw
[tp
->t_line
].l_open
)(dev
, tp
));
cnclose(dev
, flag
, mode
, p
)
register struct tty
*tp
= &cons
;
(*linesw
[tp
->t_line
].l_close
)(tp
, flag
);
register struct tty
*tp
= &cons
;
return ((*linesw
[tp
->t_line
].l_read
)(tp
, uio
, flag
));
if ((tp
= constty
) == NULL
||
(tp
->t_state
& (TS_CARR_ON
|TS_ISOPEN
)) != (TS_CARR_ON
|TS_ISOPEN
))
return ((*linesw
[tp
->t_line
].l_write
)(tp
, uio
, flag
));
cnioctl(dev
, cmd
, data
, flag
, p
)
* Superuser can always use this to wrest control of console
* output from the "virtual" console.
if (cmd
== TIOCCONS
&& constty
) {
error
= suser(p
->p_ucred
, (u_short
*)NULL
);
if ((error
= linesw
[tp
->t_line
].l_ioctl(tp
, cmd
, data
, flag
, p
)) >= 0)
if ((error
= ttioctl(tp
, cmd
, data
, flag
)) >= 0)
return (ttselect(makedev(major(dev
), 0), which
, p
));
* The rest of this code is run only when we are using the ROM vectors.
* Generic output. We just call putchar. (Very bad for performance.)
register void (*putc
)(int);
if (tp
->t_state
& (TS_TIMEOUT
| TS_TTSTOP
)) {
putc
= promvec
->pv_putchar
;
while (tp
->t_outq
.c_cc
) {
* *%&!*& ROM monitor console putchar is not reentrant!
* splhigh/tty around it so as not to run so long with
* clock interrupts blocked.
if (tp
->t_state
& TS_ASLEEP
) { /* can't happen? */
tp
->t_state
&= ~TS_ASLEEP
;
wakeup((caddr_t
)&tp
->t_outq
);
* We use pseudo-DMA, via the ROM `write string' function, called from
* software clock interrupts.
s
= spltty(); /* paranoid: splsoftclock should suffice */
if (tp
->t_state
& (TS_TIMEOUT
| TS_BUSY
| TS_TTSTOP
)) {
* If there are sleepers, and output has drained below low
if (tp
->t_outq
.c_cc
<= tp
->t_lowat
) {
if (tp
->t_state
& TS_ASLEEP
) {
tp
->t_state
&= ~TS_ASLEEP
;
wakeup((caddr_t
)&tp
->t_outq
);
* Stop frame buffer output: just assert TS_FLUSH if necessary.
register int s
= spltty(); /* paranoid */
if ((tp
->t_state
& (TS_BUSY
| TS_TTSTOP
)) == TS_BUSY
)
* Do pseudo-dma (called from software interrupt).
register struct tty
*tp
= tpaddr
;
s
= spltty(); /* paranoid */
if (tp
->t_state
& TS_FLUSH
) {
tp
->t_state
&= ~(TS_BUSY
| TS_FLUSH
);
n
= ndqb(&tp
->t_outq
, 0);
for (q
= p
, c
= n
; --c
>= 0; q
++)
if (*q
& 0200) /* high bits seem to be bad */
(*promvec
->pv_putstr
)(p
, n
);
(*linesw
[tp
->t_line
].l_start
)(tp
);
* The following is for rom console input. The rom will not call
* an `interrupt' routine on console input ready, so we must poll.
* This is all rather sad.
volatile int cn_rxc
; /* XXX receive `silo' */
/* called from hardclock, which is above spltty, so no tty calls! */
if ((c
= (*promvec
->pv_nbgetchar
)()) < 0)
/* pseudo console software interrupt scheduled when cnrom() returns 1 */
if ((tp
->t_cflag
& CSIZE
) == CS7
) {
/* XXX this should be done elsewhere, if at all */
if (tp
->t_cflag
& PARENB
)
if (tp
->t_cflag
& PARODD
?
(partab
[c
& 0177] & 0200) == (c
& 0200) :
(partab
[c
& 0177] & 0200) != (c
& 0200))
(*linesw
[tp
->t_line
].l_rint
)(c
, tp
);
c
= (*promvec
->pv_getchar
)();
register int s
= splhigh();
(*promvec
->pv_putchar
)('\r');
(*promvec
->pv_putchar
)(c
);