* Copyright (c) 1988 University of Utah.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* from: Utah $Hdr: ite.c 1.28 92/12/20$
* @(#)ite.c 8.3 (Berkeley) 1/9/95
* Bit-mapped display terminal emulator machine independent code.
* This is a very rudimentary. Much more can be abstracted out of
* the hardware dependent routines.
#include <hp/dev/grfioctl.h>
#include <hp/dev/grfvar.h>
#include <hp/dev/itevar.h>
#include <hp/dev/kbdmap.h>
#define set_attr(ip, attr) ((ip)->attribute |= (attr))
#define clr_attr(ip, attr) ((ip)->attribute &= ~(attr))
* No need to raise SPL above the HIL (the only thing that can
#include <hp/dev/hilreg.h>
#define splite() splhil()
* # of chars are output in a single itestart() call.
* If this is too big, user processes will be blocked out for
* long periods of time while we are emptying the queue in itestart().
* If it is too small, console output will be very ragged.
struct tty
*kbd_tty
= NULL
;
struct tty ite_tty
[NITE
];
struct ite_softc ite_softc
[NITE
];
void itestart(), iterestart();
extern struct tty
*constty
;
* Primary attribute buffer to be used by the first bitmapped console
* found. Secondary displays alloc the attribute buffer as needed.
* Size is based on a 68x128 display, which is currently our largest.
u_char console_attributes
[0x2200];
#define ite_erasecursor(ip, sp) { \
if ((ip)->flags & ITE_CURSORON) \
(*(sp)->ite_cursor)((ip), ERASE_CURSOR); \
#define ite_drawcursor(ip, sp) { \
if ((ip)->flags & ITE_CURSORON) \
(*(sp)->ite_cursor)((ip), DRAW_CURSOR); \
#define ite_movecursor(ip, sp) { \
if ((ip)->flags & ITE_CURSORON) \
(*(sp)->ite_cursor)((ip), MOVE_CURSOR); \
* Perform functions necessary to setup device as a terminal emulator.
struct tty
*tp
= &ite_tty
[unit
];
struct ite_softc
*ip
= &ite_softc
[unit
];
if (unit
< 0 || unit
>= NITE
|| (ip
->flags
&ITE_ALIVE
) == 0)
/* force ite active, overriding graphics mode */
ip
->flags
&= ~(ITE_INGRF
|ITE_INITED
);
/* leave graphics mode */
if ((ip
->flags
& ITE_ACTIVE
) == 0)
if (ip
->flags
& ITE_INGRF
)
if (kbd_tty
== NULL
|| kbd_tty
== tp
) {
struct ite_softc
*ip
= &ite_softc
[unit
];
if (ip
->flags
& ITE_INITED
)
(*ip
->isw
->ite_init
)(ip
);
ip
->flags
|= ITE_CURSORON
;
ite_drawcursor(ip
, ip
->isw
);
malloc(ip
->rows
* ip
->cols
, M_DEVBUF
, M_WAITOK
);
bzero(ip
->attrbuf
, (ip
->rows
* ip
->cols
));
* "Shut down" device as terminal emulator.
* Note that we do not deinit the console device unless forced.
* Deinit'ing the console every time leads to a very active
* screen when processing /etc/rc.
register struct ite_softc
*ip
= &ite_softc
[UNIT(dev
)];
ip
->flags
&= ~ITE_CURSORON
;
if ((ip
->flags
& ITE_ACTIVE
) == 0)
(ip
->flags
& (ITE_INGRF
|ITE_ISCONS
|ITE_INITED
)) == ITE_INITED
)
(*ip
->isw
->ite_deinit
)(ip
);
ip
->flags
&= ~ITE_ACTIVE
;
iteopen(dev_t dev
, int mode
, int devtype
, struct proc
*p
)
iteopen(dev
, mode
, devtype
, p
)
register struct tty
*tp
= &ite_tty
[unit
];
register struct ite_softc
*ip
= &ite_softc
[unit
];
if ((tp
->t_state
&(TS_ISOPEN
|TS_XCLUDE
)) == (TS_ISOPEN
|TS_XCLUDE
)
&& p
->p_ucred
->cr_uid
!= 0)
if ((ip
->flags
& ITE_ACTIVE
) == 0) {
if ((tp
->t_state
&TS_ISOPEN
) == 0) {
tp
->t_iflag
= TTYDEF_IFLAG
;
tp
->t_oflag
= TTYDEF_OFLAG
;
tp
->t_lflag
= TTYDEF_LFLAG
;
tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
tp
->t_state
= TS_ISOPEN
|TS_CARR_ON
;
error
= (*linesw
[tp
->t_line
].l_open
)(dev
, tp
);
tp
->t_winsize
.ws_row
= ip
->rows
;
tp
->t_winsize
.ws_col
= ip
->cols
;
iteclose(dev
, flag
, mode
, p
)
register struct tty
*tp
= &ite_tty
[UNIT(dev
)];
(*linesw
[tp
->t_line
].l_close
)(tp
, flag
);
register struct tty
*tp
= &ite_tty
[UNIT(dev
)];
return ((*linesw
[tp
->t_line
].l_read
)(tp
, uio
, flag
));
register struct tty
*tp
= &ite_tty
[unit
];
if ((ite_softc
[unit
].flags
& ITE_ISCONS
) && constty
&&
(constty
->t_state
&(TS_CARR_ON
|TS_ISOPEN
))==(TS_CARR_ON
|TS_ISOPEN
))
return ((*linesw
[tp
->t_line
].l_write
)(tp
, uio
, flag
));
iteioctl(dev
, cmd
, addr
, flag
, p
)
register struct tty
*tp
= &ite_tty
[UNIT(dev
)];
error
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, addr
, flag
, p
);
error
= ttioctl(tp
, cmd
, addr
, flag
);
register int s
= splite();
tp
->t_state
&= ~TS_TIMEOUT
;
int hiwat
= 0, hadcursor
= 0;
* (Potentially) lower priority. We only need to protect ourselves
* from keyboard interrupts since that is all that can affect the
* state of our tty (kernel printf doesn't go through this routine).
if (tp
->t_state
& (TS_TIMEOUT
|TS_BUSY
|TS_TTSTOP
)) {
if (tp
->t_state
& TS_ASLEEP
) {
tp
->t_state
&= ~TS_ASLEEP
;
wakeup((caddr_t
)&tp
->t_outq
);
iteputchar(getc(&tp
->t_outq
), tp
->t_dev
);
* Limit the amount of output we do in one burst
* to prevent hogging the CPU.
* Turn off cursor while we output multiple characters.
* Saves a lot of expensive window move operations.
ip
= &ite_softc
[UNIT(tp
->t_dev
)];
if (ip
->flags
& ITE_CURSORON
) {
ite_erasecursor(ip
, ip
->isw
);
ip
->flags
&= ~ITE_CURSORON
;
iteputchar(getc(&tp
->t_outq
), tp
->t_dev
);
ip
->flags
|= ITE_CURSORON
;
ite_drawcursor(ip
, ip
->isw
);
tp
->t_state
|= TS_TIMEOUT
;
timeout(iterestart
, tp
, 1);
register char code
, *str
;
switch ((stat
>>KBD_SSHIFT
) & KBD_SMASK
) {
code
= kbd_ctrlshiftmap
[c
];
if (code
== NULL
&& (str
= kbd_stringmap
[c
]) != NULL
) {
(*linesw
[kbd_tty
->t_line
].l_rint
)(*str
++, kbd_tty
);
(*linesw
[kbd_tty
->t_line
].l_rint
)(code
, kbd_tty
);
register struct ite_softc
*ip
= &ite_softc
[unit
];
register struct itesw
*sp
= ip
->isw
;
if ((ip
->flags
& (ITE_ACTIVE
|ITE_INGRF
)) != ITE_ACTIVE
)
case '&': /* Next can be a,d, or s */
case 'a': /* cursor change */
case 'Y': /* Only y coord. */
ip
->cury
= min(ip
->pos
, ip
->rows
-1);
case 'y': /* y coord first */
ip
->cury
= min(ip
->pos
, ip
->rows
-1);
ip
->curx
= min(ip
->pos
, ip
->cols
-1);
default: /* Possibly a 3 digit number. */
if (c
>= '0' && c
<= '9' && ip
->fpd
< 3) {
ip
->pos
= ip
->pos
* 10 + (c
- '0');
case 'd': /* attribute change */
/* XXX: we don't do anything for underline */
case 's': /* keypad control */
if (ip
->curx
> TABSIZE
) {
n
= ip
->curx
- (ip
->curx
& (TABSIZE
- 1));
case '3': /* clear all tabs */
case 'K': /* clear_eol */
ite_clrtoeol(ip
, sp
, ip
->cury
, ip
->curx
);
case 'J': /* clear_eos */
case 'B': /* cursor down 1 line */
if (++ip
->cury
== ip
->rows
) {
(*sp
->ite_scroll
)(ip
, 1, 0, 1, SCROLL_UP
);
ite_clrtoeol(ip
, sp
, ip
->cury
, 0);
case 'C': /* cursor forward 1 char */
case 'A': /* cursor up 1 line */
case 'P': /* delete character */
case 'M': /* delete line */
case 'Q': /* enter insert mode */
case 'R': /* exit insert mode */
case 'L': /* insert blank line */
case 'D': /* left arrow key */
case '1': /* set tab in all rows */
if ((ip
->escape
= c
) == ESC
)
if (++ip
->cury
== ip
->rows
) {
(*sp
->ite_scroll
)(ip
, 1, 0, 1, SCROLL_UP
);
ite_clrtoeol(ip
, sp
, ip
->cury
, 0);
if (ip
->curx
< TABEND(unit
)) {
n
= TABSIZE
- (ip
->curx
& (TABSIZE
- 1));
if (&ite_tty
[unit
] == kbd_tty
)
if ((ip
->attribute
& ATTR_INV
) || attrtest(ip
, ATTR_INV
)) {
(*sp
->ite_putc
)(ip
, c
, ip
->cury
, ip
->curx
, ATTR_INV
);
(*sp
->ite_putc
)(ip
, c
, ip
->cury
, ip
->curx
, ATTR_NOR
);
register struct ite_softc
*ip
;
register struct itesw
*sp
;
if (++ip
->curx
== ip
->cols
) {
if (++ip
->cury
== ip
->rows
) {
(*sp
->ite_scroll
)(ip
, 1, 0, 1, SCROLL_UP
);
ite_clrtoeol(ip
, sp
, ip
->cury
, 0);
register struct ite_softc
*ip
;
register struct itesw
*sp
;
if (ip
->curx
< ip
->cols
- 1) {
(*sp
->ite_scroll
)(ip
, ip
->cury
, ip
->curx
+ 1, 1, SCROLL_LEFT
);
attrmov(ip
, ip
->cury
, ip
->curx
+ 1, ip
->cury
, ip
->curx
,
1, ip
->cols
- ip
->curx
- 1);
attrclr(ip
, ip
->cury
, ip
->cols
- 1, 1, 1);
(*sp
->ite_putc
)(ip
, ' ', ip
->cury
, ip
->cols
- 1, ATTR_NOR
);
register struct ite_softc
*ip
;
register struct itesw
*sp
;
if (ip
->curx
< ip
->cols
- 1) {
(*sp
->ite_scroll
)(ip
, ip
->cury
, ip
->curx
, 1, SCROLL_RIGHT
);
attrmov(ip
, ip
->cury
, ip
->curx
, ip
->cury
, ip
->curx
+ 1,
1, ip
->cols
- ip
->curx
- 1);
attrclr(ip
, ip
->cury
, ip
->curx
, 1, 1);
(*sp
->ite_putc
)(ip
, ' ', ip
->cury
, ip
->curx
, ATTR_NOR
);
register struct ite_softc
*ip
;
register struct itesw
*sp
;
if (ip
->cury
< ip
->rows
- 1) {
(*sp
->ite_scroll
)(ip
, ip
->cury
+ 1, 0, 1, SCROLL_UP
);
attrmov(ip
, ip
->cury
+ 1, 0, ip
->cury
, 0,
ip
->rows
- ip
->cury
- 1, ip
->cols
);
ite_clrtoeol(ip
, sp
, ip
->rows
- 1, 0);
register struct ite_softc
*ip
;
register struct itesw
*sp
;
if (ip
->cury
< ip
->rows
- 1) {
(*sp
->ite_scroll
)(ip
, ip
->cury
, 0, 1, SCROLL_DOWN
);
attrmov(ip
, ip
->cury
, 0, ip
->cury
+ 1, 0,
ip
->rows
- ip
->cury
- 1, ip
->cols
);
ite_clrtoeol(ip
, sp
, ip
->cury
, 0);
ite_clrtoeol(ip
, sp
, y
, x
)
register struct ite_softc
*ip
;
register struct itesw
*sp
;
(*sp
->ite_clear
)(ip
, y
, x
, 1, ip
->cols
- x
);
attrclr(ip
, y
, x
, 1, ip
->cols
- x
);
register struct ite_softc
*ip
;
register struct itesw
*sp
;
(*sp
->ite_clear
)(ip
, ip
->cury
, 0, ip
->rows
- ip
->cury
, ip
->cols
);
attrclr(ip
, ip
->cury
, 0, ip
->rows
- ip
->cury
, ip
->cols
);
#include <hp/dev/grfreg.h>
* Minimum ITE number at which to start looking for a console.
* Setting to 0 will do normal search, 1 will skip first ITE device,
* NITE will skip ITEs and use serial port.
register struct ite_softc
*ip
;
int i
, sw
, maj
, unit
, pri
;
/* locate the major number */
for (maj
= 0; maj
< nchrdev
; maj
++)
if (cdevsw
[maj
].d_open
== iteopen
)
/* check all the individual displays and find the best */
for (i
= 0; i
< NITE
; i
++) {
struct grf_softc
*gp
= &grf_softc
[i
];
if ((gp
->g_flags
& GF_ALIVE
) == 0)
ip
->flags
= (ITE_ALIVE
|ITE_CONSOLE
);
/* locate the proper switch table. */
for (sw
= 0; sw
< nitesw
; sw
++)
if (itesw
[sw
].ite_hwid
== gp
->g_sw
->gd_hwid
)
if ((int)gp
->g_display
.gd_regaddr
== GRFIADDR
) {
/* XXX use the first one for now */
/* initialize required fields */
cp
->cn_dev
= makedev(maj
, unit
);
cp
->cn_tp
= &ite_tty
[unit
];
int unit
= UNIT(cp
->cn_dev
);
struct ite_softc
*ip
= &ite_softc
[unit
];
ip
->attrbuf
= console_attributes
;
ip
->flags
|= (ITE_ACTIVE
|ITE_ISCONS
);
kbd_tty
= &ite_tty
[unit
];
c
= kbdgetc(0, &stat
); /* XXX always read from keyboard 0 for now */
switch ((stat
>> KBD_SSHIFT
) & KBD_SMASK
) {
c
= kbd_shiftmap
[c
& KBD_CHARMASK
];
c
= kbd_ctrlmap
[c
& KBD_CHARMASK
];
c
= kbd_keymap
[c
& KBD_CHARMASK
];
struct ite_softc
*ip
= &ite_softc
[UNIT(dev
)];
if (panicstr
&& !paniced
&&
(ip
->flags
& (ITE_ACTIVE
|ITE_INGRF
)) != ITE_ACTIVE
) {