* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* William Jolitz and Don Ahn.
* 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
* Heavily modified by Søren Schmidt (sos@login.dkuug.dk) to provide:
* virtual consoles, SYSV ioctl's, ANSI emulation
* @(#)syscons.c 1.0 930928
* @(#)pccons.c 5.11 (Berkeley) 5/21/91
#include "machine/console.h"
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "i386/isa/isa_device.h"
#include "machine/pc/display.h"
#include "i386/i386/cons.h"
#include "machine/frame.h"
#define LOCK_KEY_MASK 0x0000F
#define UNKNOWN_MODE 0x00010
#define KBD_RAW_MODE 0x00020
#define SWITCH_WAIT_REL 0x00040
#define SWITCH_WAIT_ACQ 0x00080
/* virtual video memory addresses */
#define MONO_BUF 0xFE0B0000
#define CGA_BUF 0xFE0B8000
#define VGA_BUF 0xFE0A0000
#define VIDEOMEM 0x000A0000
#define MEMSIZE 0x00020000
#define XTALSPEED 1193182 /* should be in isa.h */
/* defines related to hardware addresses */
#define MONO_BASE 0x3B4 /* crt controller base mono */
#define COLOR_BASE 0x3D4 /* crt controller base color */
#define ATC IO_VGA+0x00 /* attribute controller */
#define TSIDX IO_VGA+0x04 /* timing sequencer idx */
#define TSREG IO_VGA+0x05 /* timing sequencer data */
#define PIXMASK IO_VGA+0x06 /* pixel write mask */
#define PALRADR IO_VGA+0x07 /* palette read address */
#define PALWADR IO_VGA+0x08 /* palette write address */
#define PALDATA IO_VGA+0x09 /* palette data register */
#define GDCIDX IO_VGA+0x0E /* graph data controller idx */
#define GDCREG IO_VGA+0x0F /* graph data controller data */
typedef struct term_stat
{
int esc
; /* processing escape sequence */
int n_par
; /* # of parameters to ESC */
int last_par
; /* last parameter # */
int par
[MAX_ESC_PAR
]; /* contains ESC parameters */
int attr
; /* current attributes */
int std_attr
; /* normal attributes */
int rev_attr
; /* reverse attributes */
typedef struct scr_stat
{
u_short
*crt_base
; /* address of screen memory */
u_short
*scr
; /* buffer when off screen */
u_short
*crtat
; /* cursor address */
int posx
; /* current X position */
int posy
; /* current Y position */
int max_posx
; /* X size */
int max_posy
; /* X size */
term_stat term
; /* terminal emulation stuff */
char cursor_start
; /* cursor start line # */
char cursor_end
; /* cursor start end # */
u_char border
; /* border color */
u_short status
; /* status (bitfield) */
pid_t pid
; /* pid of controlling proc */
struct proc
*proc
; /* proc* of controlling proc */
struct vt_mode smode
; /* switch mode */
typedef struct default_attr
{
int std_attr
; /* normal attributes */
int rev_attr
; /* reverse attributes */
static default_attr user_default
= {
(FG_LIGHTGREY
| BG_BLACK
) << 8,
(FG_BLACK
| BG_LIGHTGREY
) << 8
static default_attr kernel_default
= {
(FG_WHITE
| BG_BLACK
) << 8,
(FG_BLACK
| BG_LIGHTGREY
) << 8
static default_attr
*current_default
;
static scr_stat cons_scr_stat
[NCONS
];
static scr_stat
*cur_scr_stat
= &cons_scr_stat
[0];
static scr_stat
*new_scp
, *old_scp
;
static term_stat kernel_console
;
static int switch_in_progress
= 0;
u_short
*Crtat
= (u_short
*)MONO_BUF
;
static u_short
*crtat
= 0;
static u_int crtc_addr
= MONO_BASE
;
static char crtc_vga
= 0;
static u_char shfts
= 0, ctls
= 0, alts
= 0, agrs
= 0;
static u_char nlkcnt
= 0, clkcnt
= 0, slkcnt
= 0, alkcnt
= 0;
static char palette
[3*256];
static const u_int n_fkey_tab
= sizeof(fkey_tab
) / sizeof(*fkey_tab
);
static int cur_cursor_pos
= -1;
static char in_putc
, nx_scr
;
static char saved_console
= -1; /* saved console number */
static long scrn_blank_time
= 0; /* screen saver timout value */
static int scrn_blanked
= 0; /* screen saver active flag */
static long scrn_time_stamp
;
static u_char scr_map
[256];
struct tty pccons
[NCONS
];
struct tty
*cur_pccons
= &pccons
[0];
extern struct timeval time
;
#define CSF_ACTIVE 0x1 /* timeout active */
#define CSF_POLLING 0x2 /* polling for input */
char cs_lastc
; /* last char sent */
int cs_timo
; /* timeouts since interrupt */
u_long cs_wedgecnt
; /* times restarted */
} pcconsoftc
= {0, 0, 0, 0};
/* function prototypes */
int pcprobe(struct isa_device
*dev
);
int pcattach(struct isa_device
*dev
);
int pcopen(dev_t dev
, int flag
, int mode
, struct proc
*p
);
int pcclose(dev_t dev
, int flag
, int mode
, struct proc
*p
);
int pcread(dev_t dev
, struct uio
*uio
, int flag
);
int pcwrite(dev_t dev
, struct uio
*uio
, int flag
);
int pcparam(struct tty
*tp
, struct termios
*t
);
int pcioctl(dev_t dev
, int cmd
, caddr_t data
, int flag
, struct proc
*p
);
int pcstart(struct tty
*tp
);
int pccnprobe(struct consdev
*cp
);
int pccninit(struct consdev
*cp
);
int pccnputc(dev_t dev
, char c
);
int scintr(dev_t dev
, int irq
, int cpl
);
void scrn_saver(int test
);
static struct tty
*get_pccons(dev_t dev
);
static scr_stat
*get_scr_stat(dev_t dev
);
static int get_scr_num(scr_stat
*scp
);
static void cursor_shape(int start
, int end
);
static void get_cursor_shape(int *start
, int *end
);
static void cursor_pos(void);
static void clear_screen(scr_stat
*scp
);
static switch_scr(u_int next_scr
);
static void exchange_scr(void);
static void move_crsr(scr_stat
*scp
, int x
, int y
);
static void move_up(u_short
*s
, u_short
*d
, u_int len
);
static void move_down(u_short
*s
, u_short
*d
, u_int len
);
static void scan_esc(scr_stat
*scp
, u_char c
);
static void ansi_put(scr_stat
*scp
, u_char c
);
static void sput(u_char c
);
static u_char
*get_fstr(u_int c
, u_int
*len
);
static update_leds(int which
);
u_int
sgetc(int noblock
);
int pcmmap(dev_t dev
, int offset
, int nprot
);
static void kbd_wait(void);
static void kbd_cmd(u_char command
);
static void set_mode(scr_stat
*scp
);
static void set_border(int color
);
static load_font(int segment
, int size
, char* font
);
static void save_palette(void);
static void load_palette(void);
static change_winsize(struct tty
*tp
, int x
, int y
);
struct isa_driver scdriver
= {
int pcprobe(struct isa_device
*dev
)
/* Enable interrupts and keyboard controller */
/* Start keyboard stuff RESET */
while ((c
=inb(KB_DATA
)) != KB_ACK
) {
if ((c
== 0xFE) || (c
== 0xFF)) {
printf("KEYBOARD disconnected: RECONNECT \n");
int pcattach(struct isa_device
*dev
)
int start
= -1, end
= -1, i
;
if (crtc_addr
== MONO_BASE
)
if (crtc_addr
== MONO_BASE
)
printf(" <%d virtual consoles>\n", NCONS
);
get_cursor_shape(&start
, &end
);
load_font(0, 16, font_8x16
);
load_font(1, 8, font_8x8
);
load_font(2, 14, font_8x14
);
current_default
= &user_default
;
for (i
= 0; i
< NCONS
; i
++) {
scp
->scr
= (u_short
*)malloc(COL
* ROW
* 2, M_DEVBUF
, M_NOWAIT
);
scp
->term
.std_attr
= current_default
->std_attr
;
scp
->term
.rev_attr
= current_default
->rev_attr
;
scp
->term
.attr
= scp
->term
.std_attr
;
scp
->cursor_start
= start
;
scp
->smode
.mode
= VT_AUTO
;
scp
->crt_base
= scp
->crtat
= scp
->scr
;
fillw(scp
->term
.attr
|scr_map
[0x20], scp
->scr
, COL
*ROW
);
cursor_shape(cons_scr_stat
[0].cursor_start
,
cons_scr_stat
[0].cursor_end
);
static struct tty
*get_pccons(dev_t dev
)
static scr_stat
*get_scr_stat(dev_t dev
)
return(&cons_scr_stat
[i
]);
static int get_scr_num(scr_stat
*scp
) /* allways call with legal scp !! */
while ((i
< NCONS
) && (cur_scr_stat
!= &cons_scr_stat
[i
])) i
++;
pcopen(dev_t dev
, int flag
, int mode
, struct proc
*p
)
struct tty
*tp
= get_pccons(dev
);
if ((tp
->t_state
& TS_ISOPEN
) == 0) {
tp
->t_iflag
= TTYDEF_IFLAG
;
tp
->t_oflag
= TTYDEF_OFLAG
;
tp
->t_cflag
= TTYDEF_CFLAG
;
tp
->t_lflag
= TTYDEF_LFLAG
;
tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
pcparam(tp
, &tp
->t_termios
);
} else if (tp
->t_state
&TS_XCLUDE
&& p
->p_ucred
->cr_uid
!= 0)
tp
->t_state
|= TS_CARR_ON
;
return((*linesw
[tp
->t_line
].l_open
)(dev
, tp
));
pcclose(dev_t dev
, int flag
, int mode
, struct proc
*p
)
struct tty
*tp
= get_pccons(dev
);
scp
= get_scr_stat(tp
->t_dev
);
scp
->smode
.mode
= VT_AUTO
;
(*linesw
[tp
->t_line
].l_close
)(tp
, flag
);
pcread(dev_t dev
, struct uio
*uio
, int flag
)
struct tty
*tp
= get_pccons(dev
);
return((*linesw
[tp
->t_line
].l_read
)(tp
, uio
, flag
));
pcwrite(dev_t dev
, struct uio
*uio
, int flag
)
struct tty
*tp
= get_pccons(dev
);
return((*linesw
[tp
->t_line
].l_write
)(tp
, uio
, flag
));
* Got a console interrupt, keyboard action !
* Catch the character, and see who it goes to.
scintr(dev_t dev
, int irq
, int cpl
)
/* make screensaver happy */
scrn_time_stamp
= time
.tv_sec
;
if ((cur_pccons
->t_state
& TS_ISOPEN
) == 0)
if (pcconsoftc
.cs_flags
& CSF_POLLING
)
(*linesw
[cur_pccons
->t_line
].l_rint
)(c
& 0xFF, cur_pccons
);
else if (cp
= get_fstr((u_int
)c
, (u_int
*)&len
)) {
(*linesw
[cur_pccons
->t_line
].l_rint
)
(*cp
++ & 0xFF, cur_pccons
);
pcparam(struct tty
*tp
, struct termios
*t
)
tp
->t_ispeed
= t
->c_ispeed
;
tp
->t_ospeed
= t
->c_ospeed
;
pcioctl(dev_t dev
, int cmd
, caddr_t data
, int flag
, struct proc
*p
)
scp
= get_scr_stat(tp
->t_dev
);
switch (cmd
) { /* process console hardware related ioctl's */
case CONS_BLANKTIME
: /* set screen saver timeout (0 = no saver) */
scrn_blank_time
= *(int*)data
;
case CONS_80x25TEXT
: /* set 80x25 text mode */
free(scp
->scr
, M_DEVBUF
);
scp
->scr
= (u_short
*)malloc(scp
->max_posx
*scp
->max_posy
*2,
scp
->crt_base
= scp
->scr
;
change_winsize(tp
, scp
->max_posx
, scp
->max_posy
);
case CONS_80x50TEXT
: /* set 80x50 text mode */
free(scp
->scr
, M_DEVBUF
);
scp
->scr
= (u_short
*)malloc(scp
->max_posx
*scp
->max_posy
*2,
scp
->crt_base
= scp
->scr
;
change_winsize(tp
, scp
->max_posx
, scp
->max_posy
);
case CONS_GETVERS
: /* get version number */
*(int*)data
= 0x100; /* version 1.0 */
case CONS_GETINFO
: /* get current (virtual) console info */
if (*data
== sizeof(struct vid_info
)) {
vid_info_t
*ptr
= (vid_info_t
*)data
;
ptr
->m_num
= get_scr_num(scp
);
ptr
->mv_csz
= scp
->max_posx
;
ptr
->mv_rsz
= scp
->max_posy
;
ptr
->mv_norm
.fore
= (scp
->term
.std_attr
& 0x0f00)>>8;
ptr
->mv_norm
.back
= (scp
->term
.std_attr
& 0xf000)>>12;
ptr
->mv_rev
.fore
= (scp
->term
.rev_attr
& 0x0f00)>>8;
ptr
->mv_rev
.back
= (scp
->term
.rev_attr
& 0xf000)>>12;
ptr
->mv_grfc
.fore
= 0; /* not supported */
ptr
->mv_grfc
.back
= 0; /* not supported */
ptr
->mv_ovscan
= scp
->border
;
ptr
->mk_keylock
= scp
->status
& LOCK_KEY_MASK
;
case VT_SETMODE
: /* set screen switcher mode */
bcopy(data
, &scp
->smode
, sizeof(struct vt_mode
));
if (scp
->smode
.mode
== VT_PROCESS
) {
scp
->pid
= scp
->proc
->p_pid
;
case VT_GETMODE
: /* get screen switcher mode */
bcopy(&scp
->smode
, data
, sizeof(struct vt_mode
));
case VT_RELDISP
: /* screen switcher ioctl */
case VT_FALSE
: /* user refuses to release screen, abort */
if (scp
== old_scp
&& (scp
->status
& SWITCH_WAIT_REL
)) {
old_scp
->status
&= ~SWITCH_WAIT_REL
;
case VT_TRUE
: /* user has released screen, go on */
if (scp
== old_scp
&& (scp
->status
& SWITCH_WAIT_REL
)) {
scp
->status
&= ~SWITCH_WAIT_REL
;
if (new_scp
->smode
.mode
== VT_PROCESS
) {
new_scp
->status
|= SWITCH_WAIT_ACQ
;
case VT_ACKACQ
: /* acquire acknowledged, switch completed */
if (scp
== new_scp
&& (scp
->status
& SWITCH_WAIT_ACQ
)) {
scp
->status
&= ~SWITCH_WAIT_ACQ
;
case VT_OPENQRY
: /* return free virtual console */
for (i
= 0; i
< NCONS
; i
++)
if (!(pccons
[i
].t_state
& TS_ISOPEN
)) {
case VT_ACTIVATE
: /* switch to screen *data */
return switch_scr((*data
) - 1);
case VT_WAITACTIVE
: /* wait for switch to occur */
if (minor(dev
) == (*data
) - 1)
while ((error
=tsleep(&scp
->smode
,
PZERO
|PCATCH
, "waitvt", 0))
while ((error
=tsleep(&cons_scr_stat
[*data
].smode
,
PZERO
|PCATCH
, "waitvt", 0))
case KDENABIO
: /* allow io operations */
fp
= (struct syscframe
*)p
->p_regs
;
fp
->sf_eflags
|= PSL_IOPL
;
case KDDISABIO
: /* disallow io operations (default) */
fp
= (struct syscframe
*)p
->p_regs
;
fp
->sf_eflags
&= ~PSL_IOPL
;
case KDSETMODE
: /* set current mode of this (virtual) console */
case KD_TEXT
: /* switch to TEXT (known) mode */
/* restore fonts & palette ! */
load_font(0, 16, font_8x16
);
load_font(1, 8, font_8x8
);
load_font(2, 14, font_8x14
);
case KD_TEXT1
: /* switch to TEXT (known) mode */
/* no restore fonts & palette */
scp
->status
&= ~UNKNOWN_MODE
;
case KD_GRAPHICS
:/* switch to GRAPHICS (unknown) mode */
scp
->status
|= UNKNOWN_MODE
;
case KDGETMODE
: /* get current mode of this (virtual) console */
*data
= (scp
->status
& UNKNOWN_MODE
) ? KD_GRAPHICS
: KD_TEXT
;
case KDSBORDER
: /* set border color of this (virtual) console */
case KDSKBSTATE
: /* set keyboard state (locks) */
if (*data
>= 0 && *data
<= LOCK_KEY_MASK
) {
scp
->status
&= ~LOCK_KEY_MASK
;
update_leds(scp
->status
& LED_MASK
);
case KDGKBSTATE
: /* get keyboard state (locks) */
*data
= scp
->status
& LOCK_KEY_MASK
;
case KDSETRAD
: /* set keyboard repeat & delay rates */
if (*(u_char
*)data
< 0x80) {
case KDSKBMODE
: /* set keyboard mode */
case K_RAW
: /* switch to RAW scancode mode */
scp
->status
|= KBD_RAW_MODE
;
case K_XLATE
: /* switch to XLT ascii mode */
scp
->status
&= ~KBD_RAW_MODE
;
case KDGKBMODE
: /* get keyboard mode */
*data
= (scp
->status
& KBD_RAW_MODE
) ? K_RAW
: K_XLATE
;
case KDMKTONE
: /* sound the bell */
sysbeep(scp
->bell_pitch
, scp
->bell_duration
);
case KIOCSOUND
: /* make tone (*data) hz */
if (scp
== cur_scr_stat
) {
int pitch
= XTALSPEED
/(*(int*)data
);
outb(0x61, inb(0x61) | 3);
/* set command for counter 2, 2 byte write */
outb(0x61, inb(0x61) & 0xFC);
case KDGKBTYPE
: /* get keyboard type */
*data
= 0; /* type not known (yet) */
case KDSETLED
: /* set keyboard LED status */
if (*data
>= 0 && *data
<= LED_MASK
) {
scp
->status
&= ~LED_MASK
;
update_leds(scp
->status
& LED_MASK
);
case KDGETLED
: /* get keyboard LED status */
*data
= scp
->status
& LED_MASK
;
case GETFKEY
: /* get functionkey string */
if (*(u_short
*)data
< n_fkey_tab
) {
fkeyarg_t
*ptr
= (fkeyarg_t
*)data
;
bcopy(&fkey_tab
[ptr
->keynum
].str
,
fkey_tab
[ptr
->keynum
].len
);
ptr
->flen
= fkey_tab
[ptr
->keynum
].len
;
case SETFKEY
: /* set functionkey string */
if (*(u_short
*)data
< n_fkey_tab
) {
fkeyarg_t
*ptr
= (fkeyarg_t
*)data
;
&fkey_tab
[ptr
->keynum
].str
,
fkey_tab
[ptr
->keynum
].len
= min(ptr
->flen
, MAXFK
);
case GIO_SCRNMAP
: /* get output translation table */
bcopy(&scr_map
, data
, sizeof(scr_map
));
case PIO_SCRNMAP
: /* set output translation table */
bcopy(data
, &scr_map
, sizeof(scr_map
));
case GIO_KEYMAP
: /* get keyboard translation table */
bcopy(&key_map
, data
, sizeof(key_map
));
case PIO_KEYMAP
: /* set keyboard translation table */
bcopy(data
, &key_map
, sizeof(key_map
));
case PIO_FONT8x8
: /* set 8x8 dot font */
bcopy(data
, &font_8x8
, sizeof(font_8x8
));
load_font(1, 8, font_8x8
);
case GIO_FONT8x8
: /* get 8x8 dot font */
bcopy(&font_8x8
, data
, sizeof(font_8x8
));
case PIO_FONT8x14
: /* set 8x14 dot font */
bcopy(data
, &font_8x14
, sizeof(font_8x14
));
load_font(2, 14, font_8x14
);
case GIO_FONT8x14
: /* get 8x14 dot font */
bcopy(&font_8x14
, data
, sizeof(font_8x14
));
case PIO_FONT8x16
: /* set 8x16 dot font */
bcopy(data
, &font_8x16
, sizeof(font_8x16
));
load_font(0, 16, font_8x16
);
case GIO_FONT8x16
: /* get 8x16 dot font */
bcopy(&font_8x16
, data
, sizeof(font_8x16
));
case CONSOLE_X_MODE_ON
: /* just to be compatible */
saved_console
= get_scr_num(cur_scr_stat
);
fp
= (struct syscframe
*)p
->p_regs
;
fp
->sf_eflags
|= PSL_IOPL
;
scp
->status
|= UNKNOWN_MODE
;
scp
->status
|= KBD_RAW_MODE
;
case CONSOLE_X_MODE_OFF
:/* just to be compatible */
fp
= (struct syscframe
*)p
->p_regs
;
fp
->sf_eflags
&= ~PSL_IOPL
;
load_font(0, 16, font_8x16
);
load_font(1, 8, font_8x8
);
load_font(2, 14, font_8x14
);
scp
->status
&= ~UNKNOWN_MODE
;
scp
->status
&= ~KBD_RAW_MODE
;
switch_scr(saved_console
);
case CONSOLE_X_BELL
: /* more compatibility */
* if set, data is a pointer to a length 2 array of
* integers. data[0] is the pitch in Hz and data[1]
* is the duration in msec.
sysbeep(XTALSPEED
/((int*)data
)[0], ((int*)data
)[1]*hz
/3000);
error
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, data
, flag
);
error
= ttioctl(tp
, cmd
, data
, flag
);
pccons
[minor(dev
)].t_state
&= ~TS_BUSY
;
if (pccons
[minor(dev
)].t_line
)
(*linesw
[pccons
[minor(dev
)].t_line
].l_start
)
pcstart(&pccons
[minor(dev
)]);
scr_stat
*scp
= get_scr_stat(tp
->t_dev
);
if (!(tp
->t_state
& (TS_TIMEOUT
|TS_BUSY
|TS_TTSTOP
)))
if (RB_LEN(&tp
->t_out
) <= tp
->t_lowat
) {
if (tp
->t_state
& TS_ASLEEP
) {
tp
->t_state
&= ~TS_ASLEEP
;
wakeup((caddr_t
)&tp
->t_out
);
tp
->t_state
&= ~TS_WCOLL
;
if (RB_LEN(&tp
->t_out
) == 0)
pccnprobe(struct consdev
*cp
)
/* locate the major number */
for (maj
= 0; maj
< nchrdev
; maj
++)
if (cdevsw
[maj
].d_open
== pcopen
)
/* initialize required fields */
cp
->cn_dev
= makedev(maj
, 0);
cp
->cn_pri
= CN_INTERNAL
;
pccninit(struct consdev
*cp
)
pccnputc(dev_t dev
, char c
)
if (cur_scr_stat
->status
& UNKNOWN_MODE
)
pos
= cur_scr_stat
->crtat
- cur_scr_stat
->crt_base
;
if (pos
!= cur_cursor_pos
) {
outb(crtc_addr
+1,pos
>> 8);
outb(crtc_addr
+1,pos
&0xff);
s
= spltty(); /* block scintr while we poll */
#if !defined(STAR_SAVER) && !defined(SNAKE_SAVER)
void scrn_saver(int test
)
outb(TSIDX
, 0x01); val
= inb(TSREG
);
outb(TSIDX
, 0x01); outb(TSREG
, val
| 0x20);
outb(TSIDX
, 0x01); val
= inb(TSREG
);
outb(TSIDX
, 0x01); outb(TSREG
, val
& 0xDF);
#if defined(STAR_SAVER) || defined(SNAKE_SAVER)
static u_long rand_next
= 1;
return ((rand_next
= rand_next
* 1103515245 + 12345) & 0x7FFFFFFF);
* Alternate saver that got its inspiration from a well known utility
* package for an unfamous OS.
void scrn_saver(int test
)
scr_stat
*scp
= cur_scr_stat
;
char pattern
[] = {"...........++++*** "};
char colors
[] = {FG_DARKGREY
, FG_LIGHTGREY
,
static u_short stars
[NUM_STARS
][2];
scp
->max_posx
* scp
->max_posy
* 2);
fillw((FG_LIGHTGREY
|BG_BLACK
)<<8 | scr_map
[0x20], Crtat
,
scp
->max_posx
* scp
->max_posy
);
i
= scp
->max_posy
* scp
->max_posx
+ 5;
outb(crtc_addr
+1, i
>> 8);
outb(crtc_addr
+1, i
& 0xff);
for(i
=0; i
<NUM_STARS
; i
++) {
rand() % (scp
->max_posx
*scp
->max_posy
);
cell
= rand() % NUM_STARS
;
*((u_short
*)(Crtat
+ stars
[cell
][0])) =
scr_map
[pattern
[stars
[cell
][1]]] |
colors
[rand()%sizeof(colors
)] << 8;
if ((stars
[cell
][1]+=(rand()%4)) >= sizeof(pattern
)-1) {
stars
[cell
][0] = rand() % (scp
->max_posx
*scp
->max_posy
);
bcopy(scp
->scr
, Crtat
, scp
->max_posx
*scp
->max_posy
*2);
* alternative screen saver for cards that do not like blanking
void scrn_saver(int test
)
const char saves
[] = {"FreeBSD"};
static u_char
*savs
[sizeof(saves
)-1];
scr_stat
*scp
= cur_scr_stat
;
scp
->max_posx
* scp
->max_posy
* 2);
fillw((FG_LIGHTGREY
|BG_BLACK
)<<8 | scr_map
[0x20], Crtat
,
scp
->max_posx
* scp
->max_posy
);
dirx
= (scp
->posx
? 1 : -1);
scp
->max_posx
: -scp
->max_posx
);
for (f
=0; f
< sizeof(saves
)-1; f
++)
savs
[f
] = (u_char
*)Crtat
+ 2 *
(scp
->posx
+scp
->posy
*scp
->max_posx
);
*(savs
[0]) = scr_map
[*saves
];
f
= scp
->max_posy
* scp
->max_posx
+ 5;
outb(crtc_addr
+1, f
>> 8);
outb(crtc_addr
+1, f
& 0xff);
*(savs
[sizeof(saves
)-2]) = scr_map
[0x20];
for (f
=sizeof(saves
)-2; f
> 0; f
--)
f
= (savs
[0] - (u_char
*)Crtat
) / 2;
if ((f
% scp
->max_posx
) == 0 ||
(f
% scp
->max_posx
) == scp
->max_posx
- 1 ||
if ((f
/ scp
->max_posx
) == 0 ||
(f
/ scp
->max_posx
) == scp
->max_posy
- 1 ||
savs
[0] += 2*dirx
+ 2*diry
;
for (f
=sizeof(saves
)-2; f
>=0; f
--)
*(savs
[f
]) = scr_map
[saves
[f
]];
scp
->max_posx
* scp
->max_posy
* 2);
static void cursor_shape(int start
, int end
)
outb(crtc_addr
+1, start
& 0xFF);
outb(crtc_addr
+1, end
& 0xFF);
static void get_cursor_shape(int *start
, int *end
)
*start
= inb(crtc_addr
+1) & 0x1F;
*end
= inb(crtc_addr
+1) & 0x1F;
static void cursor_pos(void)
if (cur_scr_stat
->status
& UNKNOWN_MODE
)
if (scrn_blank_time
&& (time
.tv_sec
> scrn_time_stamp
+scrn_blank_time
))
pos
= cur_scr_stat
->crtat
- cur_scr_stat
->crt_base
;
if (!scrn_blanked
&& pos
!= cur_cursor_pos
) {
outb(crtc_addr
+1, pos
>>8);
outb(crtc_addr
+1, pos
&0xff);
timeout(cursor_pos
, 0, hz
/20);
static void clear_screen(scr_stat
*scp
)
fillw(scp
->term
.attr
| scr_map
[0x20], scp
->crt_base
,
scp
->max_posx
* scp
->max_posy
);
static switch_scr(u_int next_scr
)
if (in_putc
) { /* don't switch if in putc */
if (switch_in_progress
&&
(cur_scr_stat
->proc
!= pfind(cur_scr_stat
->pid
)))
if (next_scr
>= NCONS
|| switch_in_progress
) {
new_scp
= &cons_scr_stat
[next_scr
];
if (new_scp
== old_scp
) {
new_pccons
= &pccons
[next_scr
];
/* has controlling process died? */
if (old_scp
->proc
&& (old_scp
->proc
!= pfind(old_scp
->pid
)))
old_scp
->smode
.mode
= VT_AUTO
;
if (new_scp
->proc
&& (new_scp
->proc
!= pfind(new_scp
->pid
)))
new_scp
->smode
.mode
= VT_AUTO
;
/* check the modes and switch approbiatly */
if (old_scp
->smode
.mode
== VT_PROCESS
) {
old_scp
->status
|= SWITCH_WAIT_REL
;
psignal(old_scp
->proc
, old_scp
->smode
.relsig
);
if (new_scp
->smode
.mode
== VT_PROCESS
) {
new_scp
->status
|= SWITCH_WAIT_ACQ
;
psignal(new_scp
->proc
, new_scp
->smode
.acqsig
);
static void exchange_scr(void)
bcopy(Crtat
, old_scp
->scr
, old_scp
->max_posx
* old_scp
->max_posy
* 2);
old_scp
->crt_base
= old_scp
->scr
;
move_crsr(old_scp
, old_scp
->posx
, old_scp
->posy
);
if (old_scp
->status
& KBD_RAW_MODE
|| new_scp
->status
& KBD_RAW_MODE
)
update_leds(new_scp
->status
& LED_MASK
);
new_scp
->crt_base
= Crtat
;
move_crsr(new_scp
, new_scp
->posx
, new_scp
->posy
);
bcopy(new_scp
->scr
, Crtat
, new_scp
->max_posx
* new_scp
->max_posy
* 2);
static void move_crsr(scr_stat
*scp
, int x
, int y
)
if (x
< 0 || y
< 0 || x
>= scp
->max_posx
|| y
>= scp
->max_posy
)
scp
->crtat
= scp
->crt_base
+ scp
->posy
* scp
->max_posx
+ scp
->posx
;
static void move_up(u_short
*s
, u_short
*d
, u_int len
)
static void move_down(u_short
*s
, u_short
*d
, u_int len
)
static void scan_esc(scr_stat
*scp
, u_char c
)
static u_char ansi_col
[16] =
{0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
u_short
*src
, *dst
, count
;
if (scp
->term
.esc
== 1) {
case '[': /* Start ESC [ sequence */
for (i
= scp
->term
.n_par
; i
< MAX_ESC_PAR
; i
++)
case 'M': /* Move cursor up 1 line, scroll if at top */
move_crsr(scp
, scp
->posx
, scp
->posy
- 1);
scp
->crt_base
+ scp
->max_posx
,
(scp
->max_posy
- 1) * scp
->max_posx
);
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crt_base
, scp
->max_posx
);
case 'c': /* Clear screen & home */
else if (scp
->term
.esc
== 2) {
if (c
>= '0' && c
<= '9') {
if (scp
->term
.n_par
< MAX_ESC_PAR
) {
if (scp
->term
.last_par
!= scp
->term
.n_par
) {
scp
->term
.last_par
= scp
->term
.n_par
;
scp
->term
.par
[scp
->term
.n_par
] = 0;
scp
->term
.par
[scp
->term
.n_par
] *= 10;
scp
->term
.par
[scp
->term
.n_par
] += c
- '0';
scp
->term
.n_par
= scp
->term
.last_par
+ 1;
if (scp
->term
.n_par
< MAX_ESC_PAR
)
for (i
= scp
->term
.n_par
; i
< MAX_ESC_PAR
; i
++)
case 'A': /* up n rows */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, scp
->posy
- n
);
case 'B': /* down n rows */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, scp
->posy
+ n
);
case 'C': /* right n columns */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
+ n
, scp
->posy
);
case 'D': /* left n columns */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
- n
, scp
->posy
);
case 'E': /* cursor to start of line n lines down */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, 0, scp
->posy
+ n
);
case 'F': /* cursor to start of line n lines up */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, 0, scp
->posy
- n
);
case 'f': /* System V consoles .. */
case 'H': /* Cursor move */
if (scp
->term
.n_par
== 0)
else if (scp
->term
.n_par
== 2)
move_crsr(scp
, scp
->term
.par
[1] - 1,
case 'J': /* Clear all or part of display */
if (scp
->term
.n_par
== 0)
case 0: /* clear form cursor to end of display */
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crtat
, scp
->crt_base
+
scp
->max_posx
* scp
->max_posy
-
case 1: /* clear from beginning of display to cursor */
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crtat
- scp
->crt_base
);
case 2: /* clear entire display */
case 'K': /* Clear all or part of line */
if (scp
->term
.n_par
== 0)
case 0: /* clear form cursor to end of line */
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crtat
, scp
->max_posx
- scp
->posx
);
case 1: /* clear from beginning of line to cursor */
fillw(scp
->term
.attr
|scr_map
[0x20],
scp
->crtat
- (scp
->max_posx
- scp
->posx
),
(scp
->max_posx
- scp
->posx
) + 1);
case 2: /* clear entire line */
fillw(scp
->term
.attr
|scr_map
[0x20],
scp
->crtat
- (scp
->max_posx
- scp
->posx
),
case 'L': /* Insert n lines */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
if (n
> scp
->max_posy
- scp
->posy
)
n
= scp
->max_posy
- scp
->posy
;
src
= scp
->crt_base
+ scp
->posy
* scp
->max_posx
;
dst
= src
+ n
* scp
->max_posx
;
count
= scp
->max_posy
- (scp
->posy
+ n
);
move_up(src
, dst
, count
* scp
->max_posx
);
fillw(scp
->term
.attr
| scr_map
[0x20], src
,
case 'M': /* Delete n lines */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
if (n
> scp
->max_posy
- scp
->posy
)
n
= scp
->max_posy
- scp
->posy
;
dst
= scp
->crt_base
+ scp
->posy
* scp
->max_posx
;
src
= dst
+ n
* scp
->max_posx
;
count
= scp
->max_posy
- (scp
->posy
+ n
);
move_down(src
, dst
, count
* scp
->max_posx
);
src
= dst
+ count
* scp
->max_posx
;
fillw(scp
->term
.attr
| scr_map
[0x20], src
,
case 'P': /* Delete n chars */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
if (n
> scp
->max_posx
- scp
->posx
)
n
= scp
->max_posx
- scp
->posx
;
count
= scp
->max_posx
- (scp
->posx
+ n
);
move_down(src
, dst
, count
);
fillw(scp
->term
.attr
| scr_map
[0x20], src
, n
);
case '@': /* Insert n chars */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
if (n
> scp
->max_posx
- scp
->posx
)
n
= scp
->max_posx
- scp
->posx
;
count
= scp
->max_posx
- (scp
->posx
+ n
);
move_up(src
, dst
, count
);
fillw(scp
->term
.attr
| scr_map
[0x20], src
, n
);
case 'S': /* scroll up n lines */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
bcopy(scp
->crt_base
+ (scp
->max_posx
* n
),
scp
->max_posx
* (scp
->max_posy
- n
) *
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crt_base
+ scp
->max_posx
*
case 'T': /* scroll down n lines */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
scp
->crt_base
+ (scp
->max_posx
* n
),
scp
->max_posx
* (scp
->max_posy
- n
) *
fillw(scp
->term
.attr
| scr_map
[0x20], scp
->crt_base
,
case 'X': /* delete n characters in line */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crt_base
+ scp
->posx
+
((scp
->max_posx
*scp
->posy
) * sizeof(u_short
)), n
);
case 'Z': /* move n tabs backwards */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
if ((i
= scp
->posx
& 0xf8) == scp
->posx
)
move_crsr(scp
, i
, scp
->posy
);
case '`': /* move cursor to column n */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, n
, scp
->posy
);
case 'a': /* move cursor n columns to the right */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
+ n
, scp
->posy
);
case 'd': /* move cursor to row n */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, n
);
case 'e': /* move cursor n rows down */
n
= scp
->term
.par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, scp
->posy
+ n
);
case 'm': /* change attribute */
if (scp
->term
.n_par
== 0)
case 0: /* back to normal */
scp
->term
.attr
= scp
->term
.std_attr
;
case 1: /* highlight (bold) */
scp
->term
.attr
&= 0xFF00;
scp
->term
.attr
|= 0x0800;
case 4: /* highlight (underline) */
scp
->term
.attr
&= 0x0F00;
scp
->term
.attr
|= 0x0800;
scp
->term
.attr
&= 0xFF00;
scp
->term
.attr
|= 0x8000;
case 7: /* reverse video */
scp
->term
.attr
= scp
->term
.rev_attr
;
case 30: case 31: case 32: case 33: /* set fg color */
case 34: case 35: case 36: case 37:
scp
->term
.attr
= (scp
->term
.attr
& 0xF0FF)
| (ansi_col
[(n
- 30) & 7] << 8);
case 40: case 41: case 42: case 43: /* set bg color */
case 44: case 45: case 46: case 47:
scp
->term
.attr
= (scp
->term
.attr
& 0x0FFF)
| (ansi_col
[(n
- 40) & 7] << 12);
if (scp
->term
.n_par
== 0)
case 0: /* reset attributes */
scp
->term
.attr
= scp
->term
.std_attr
=
current_default
->std_attr
;
scp
->term
.rev_attr
= current_default
->rev_attr
;
case 1: /* set ansi background */
scp
->term
.attr
= scp
->term
.std_attr
=
(scp
->term
.std_attr
& 0x0F00) |
(ansi_col
[(scp
->term
.par
[1])&0x0F]<<12);
case 2: /* set ansi foreground */
scp
->term
.attr
= scp
->term
.std_attr
=
(scp
->term
.std_attr
& 0xF000) |
(ansi_col
[(scp
->term
.par
[1])&0x0F]<<8);
case 3: /* set ansi attribute directly */
scp
->term
.attr
= scp
->term
.std_attr
=
(scp
->term
.par
[1]&0xFF)<<8;
case 5: /* set ansi reverse video background */
(scp
->term
.rev_attr
& 0x0F00) |
(ansi_col
[(scp
->term
.par
[1])&0x0F]<<12);
case 6: /* set ansi reverse video foreground */
(scp
->term
.rev_attr
& 0xF000) |
(ansi_col
[(scp
->term
.par
[1])&0x0F]<<8);
case 7: /* set ansi reverse video directly */
scp
->term
.rev_attr
= (scp
->term
.par
[1]&0xFF)<<8;
case 'z': /* switch to (virtual) console n */
if (scp
->term
.n_par
== 1)
switch_scr(scp
->term
.par
[0]);
else if (scp
->term
.esc
== 3) {
if (c
>= '0' && c
<= '9') {
if (scp
->term
.n_par
< MAX_ESC_PAR
) {
if (scp
->term
.last_par
!= scp
->term
.n_par
) {
scp
->term
.last_par
= scp
->term
.n_par
;
scp
->term
.par
[scp
->term
.n_par
] = 0;
scp
->term
.par
[scp
->term
.n_par
] *= 10;
scp
->term
.par
[scp
->term
.n_par
] += c
- '0';
scp
->term
.n_par
= scp
->term
.last_par
+ 1;
if (scp
->term
.n_par
< MAX_ESC_PAR
)
case 'A': /* set display border color */
if (scp
->term
.n_par
== 1)
scp
->border
=scp
->term
.par
[0] & 0xff;
case 'B': /* set bell pitch and duration */
if (scp
->term
.n_par
== 2) {
scp
->bell_pitch
= scp
->term
.par
[0];
scp
->bell_duration
= scp
->term
.par
[1]*10;
case 'C': /* set cursor shape (start & end line) */
if (scp
->term
.n_par
== 2) {
scp
->cursor_start
= scp
->term
.par
[0] & 0x1F;
scp
->cursor_end
= scp
->term
.par
[1] & 0x1F;
cursor_shape(scp
->cursor_start
,
case 'F': /* set ansi foreground */
if (scp
->term
.n_par
== 1)
scp
->term
.attr
= scp
->term
.std_attr
=
(scp
->term
.std_attr
& 0xF000)
| ((scp
->term
.par
[0] & 0x0F) << 8);
case 'G': /* set ansi background */
if (scp
->term
.n_par
== 1)
scp
->term
.attr
= scp
->term
.std_attr
=
(scp
->term
.std_attr
& 0x0F00)
| ((scp
->term
.par
[0] & 0x0F) << 12);
case 'H': /* set ansi reverse video foreground */
if (scp
->term
.n_par
== 1)
(scp
->term
.rev_attr
& 0xF000)
| ((scp
->term
.par
[0] & 0x0F) << 8);
case 'I': /* set ansi reverse video background */
if (scp
->term
.n_par
== 1)
(scp
->term
.rev_attr
& 0x0F00)
| ((scp
->term
.par
[0] & 0x0F) << 12);
static void ansi_put(scr_stat
*scp
, u_char c
)
if (scp
->status
& UNKNOWN_MODE
)
/* make screensaver happy */
if (scp
== cur_scr_stat
) {
scrn_time_stamp
= time
.tv_sec
;
case 0x1B: /* start escape sequence */
sysbeep(scp
->bell_pitch
, scp
->bell_duration
);
case '\t': /* non-destructive tab */
scp
->crtat
+= (8 - scp
->posx
% 8);
scp
->posx
+= (8 - scp
->posx
% 8);
case '\b': /* non-destructive backspace */
if (scp
->crtat
> scp
->crt_base
) {
scp
->posx
+= scp
->max_posx
- 1;
case '\r': /* return to pos 0 */
move_crsr(scp
, 0, scp
->posy
);
case '\n': /* newline, same pos */
scp
->crtat
+= scp
->max_posx
;
case '\f': /* form feed, clears screen */
/* Print only printables */
*scp
->crtat
= (scp
->term
.attr
| scr_map
[c
]);
if (++scp
->posx
>= scp
->max_posx
) {
if (scp
->crtat
>= scp
->crt_base
+ scp
->max_posy
* scp
->max_posx
) {
bcopy(scp
->crt_base
+ scp
->max_posx
, scp
->crt_base
,
scp
->max_posx
* (scp
->max_posy
- 1) * sizeof(u_short
));
fillw(scp
->term
.attr
| scr_map
[0x20],
scp
->crt_base
+ scp
->max_posx
* (scp
->max_posy
- 1),
scp
->crtat
-= scp
->max_posx
;
u_short
volatile *cp
= Crtat
+ (CGA_BUF
-MONO_BUF
)/sizeof(u_short
), was
;
* catch that once in a blue moon occurence when consinit is called
* TWICE, adding the CGA_BUF offset again -> poooff
* Crtat initialized to point to MONO buffer, if not present change
* to CGA_BUF offset. ONLY ADD the difference since locore.s adds
* in the remapped offset at the right time
Crtat
= Crtat
+ (CGA_BUF
-MONO_BUF
)/sizeof(u_short
);
/* Extract cursor location */
cursorat
= inb(crtc_addr
+1)<<8 ;
cursorat
|= inb(crtc_addr
+1);
crtat
= Crtat
+ cursorat
;
/* is this a VGA or higher ? */
current_default
= &user_default
;
cons_scr_stat
[0].crtat
= crtat
;
cons_scr_stat
[0].crt_base
= Crtat
;
cons_scr_stat
[0].term
.esc
= 0;
cons_scr_stat
[0].term
.std_attr
= current_default
->std_attr
;
cons_scr_stat
[0].term
.rev_attr
= current_default
->rev_attr
;
cons_scr_stat
[0].term
.attr
= current_default
->std_attr
;
cons_scr_stat
[0].posx
= cursorat
% COL
;
cons_scr_stat
[0].posy
= cursorat
/ COL
;
cons_scr_stat
[0].border
= BG_BLACK
;;
cons_scr_stat
[0].max_posx
= COL
;
cons_scr_stat
[0].max_posy
= ROW
;
cons_scr_stat
[0].status
= 0;
cons_scr_stat
[0].pid
= 0;
cons_scr_stat
[0].proc
= NULL
;
cons_scr_stat
[0].smode
.mode
= VT_AUTO
;
cons_scr_stat
[0].bell_pitch
= 800;
cons_scr_stat
[0].bell_duration
= 10;
kernel_console
.std_attr
= kernel_default
.std_attr
;
kernel_console
.rev_attr
= kernel_default
.rev_attr
;
kernel_console
.attr
= kernel_default
.std_attr
;
/* initialize mapscrn array to */
for (i
=0; i
<sizeof(scr_map
); i
++)
clear_screen(&cons_scr_stat
[0]);
static void sput(u_char c
)
scr_stat
*scp
= &cons_scr_stat
[0];
scp
->term
= kernel_console
;
current_default
= &kernel_default
;
kernel_console
= scp
->term
;
current_default
= &user_default
;
static u_char
*get_fstr(u_int c
, u_int
*len
)
static update_leds(int which
)
u_char xlate_leds
[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
kbd_cmd(KB_SETLEDS
); /* LED Command */
kbd_cmd(xlate_leds
[which
& LED_MASK
]);
volatile void reset_cpu(void)
kbd_cmd(KB_RESET_CPU
); /* Reset Command */
kbd_cmd(KB_RESET
); /* Keyboard Reset Command */
* sgetc(noblock) : get a character from the keyboard.
* If noblock = 0 wait until a key is gotten. Otherwise return a 0x100.
u_char val
, code
, release
;
static u_char esc_flag
= 0, compose
= 0;
/* First see if there is something in the keyboard port */
if (inb(KB_STAT
) & KB_BUF_FULL
)
if (cur_scr_stat
->status
& KBD_RAW_MODE
)
/* Check for cntl-alt-del */
if ((code
== 83) && ctls
&& alts
)
/* Check for cntl-alt-esc */
if ((val
== 1) && ctls
&& alts
) {
/* if debugger called, try to switch to console 0 */
if (cur_scr_stat
->smode
.mode
== VT_AUTO
&&
cons_scr_stat
[0].smode
.mode
== VT_AUTO
)
case 0x00: /* normal scancode */
case 0x38: /* left alt (compose key) */
if (release
&& compose
) {
case 0x60: /* 0xE0 prefix */
case 0x1c: /* right enter key */
case 0x1d: /* right ctrl key */
case 0x35: /* keypad divide key */
case 0x37: /* print scrn key */
case 0x38: /* right alt key (alt gr) */
case 0x47: /* grey home key */
case 0x48: /* grey up arrow key */
case 0x49: /* grey page up key */
case 0x4b: /* grey left arrow key */
case 0x4d: /* grey right arrow key */
case 0x4f: /* grey end key */
case 0x50: /* grey down arrow key */
case 0x51: /* grey page down key */
case 0x52: /* grey insert key */
case 0x53: /* grey delete key */
default: /* ignore everything else */
case 0x61: /* 0xE1 prefix */
case 0x1D: /* pause / break */
case 0x48: /* keypad 7,8,9 */
chr
= (code
- 0x40) + chr
*10;
case 0x4c: /* keypad 4,5,6 */
chr
= (code
- 0x47) + chr
*10;
case 0x50: /* keypad 1,2,3 */
chr
= (code
- 0x4e) + chr
*10;
case 0x52: /* keypad 0 */
case 0x38: /* left alt key */
state
= (shfts
? 1 : 0 ) | (2 * (ctls
? 1 : 0)) | (4 * (alts
? 1 : 0));
if ((!agrs
&& (cur_scr_stat
->status
& ALKED
))
|| (agrs
&& !(cur_scr_stat
->status
& ALKED
)))
key
= &key_map
.key
[code
];
if ( ((key
->flgs
& FLAG_LOCK_C
) && (cur_scr_stat
->status
& CLKED
))
|| ((key
->flgs
& FLAG_LOCK_N
) && (cur_scr_stat
->status
& NLKED
)) )
/* Check for make/break */
action
= key
->map
[state
];
if (release
) { /* key released */
if (key
->spcl
& (0x80>>state
)) {
if (cur_scr_stat
->status
& NLKED
)
cur_scr_stat
->status
&= ~NLKED
;
cur_scr_stat
->status
|= NLKED
;
update_leds(cur_scr_stat
->status
& LED_MASK
);
if (cur_scr_stat
->status
& CLKED
)
cur_scr_stat
->status
&= ~CLKED
;
cur_scr_stat
->status
|= CLKED
;
update_leds(cur_scr_stat
->status
& LED_MASK
);
if (cur_scr_stat
->status
& SLKED
) {
cur_scr_stat
->status
&= ~SLKED
;
pcstart(&pccons
[get_scr_num(cur_scr_stat
)]);
cur_scr_stat
->status
|= SLKED
;
update_leds(cur_scr_stat
->status
& LED_MASK
);
if (cur_scr_stat
->status
& ALKED
)
cur_scr_stat
->status
&= ~ALKED
;
cur_scr_stat
->status
|= ALKED
;
if (action
>= F_SCR
&& action
<= L_SCR
) {
switch_scr(action
- F_SCR
);
if (action
>= F_FN
&& action
<= L_FN
) {
/* July '93, jkh. Added in for init_main.c */
cons_scr_stat
[0].term
.attr
&= 0xFF00;
cons_scr_stat
[0].term
.attr
|= 0x0800;
cons_scr_stat
[0].term
.attr
= cons_scr_stat
[0].term
.std_attr
;
pcconsoftc
.cs_flags
|= CSF_POLLING
;
thechar
= (char) sgetc(0);
pcconsoftc
.cs_flags
&= ~CSF_POLLING
;
if (thechar
>= scr_map
[0x20])
sput(bs
); sput(scr_map
[0x20]); sput(bs
);
sput('^'); sput('D'); sput('\r'); sput('\n');
int pcmmap(dev_t dev
, int offset
, int nprot
)
return i386_btop((VIDEOMEM
+ offset
));
static void kbd_wait(void)
if ((inb(KB_STAT
) & KB_READY
) == 0)
static void kbd_cmd(u_char command
)
static void set_mode(scr_stat
*scp
)
/* (re)activate cursor */
untimeout(cursor_pos
, 0);
/* change cursor type if set */
if (scp
->cursor_start
!= -1 && scp
->cursor_end
!= -1)
cursor_shape(scp
->cursor_start
, scp
->cursor_end
);
/* mode change only on VGA's */
/* setup video hardware for the given mode */
outb(crtc_addr
, 9); byte
= inb(crtc_addr
+1);
outb(crtc_addr
, 9); outb(crtc_addr
+1, byte
| 0x0F);
outb(TSIDX
, 0x03); outb(TSREG
, 0x00); /* select font 0 */
outb(crtc_addr
, 9); byte
= inb(crtc_addr
+1);
outb(crtc_addr
, 9); outb(crtc_addr
+1, (byte
& 0xF0) | 0x07);
outb(TSIDX
, 0x03); outb(TSREG
, 0x05); /* select font 1 */
/* set border color for this (virtual) console */
static void set_border(int color
)
inb(crtc_addr
+6); /* reset flip-flop */
outb(ATC
, 0x11); outb(ATC
, color
);
inb(crtc_addr
+6); /* reset flip-flop */
outb(ATC
, 0x20); /* enable Palette */
static load_font(int segment
, int size
, char* font
)
outb(TSIDX
, 0x01); val
= inb(TSREG
); /* blank screen */
outb(TSIDX
, 0x01); outb(TSREG
, val
| 0x20);
/* setup vga for loading fonts (graphics plane mode) */
inb(crtc_addr
+6); /* reset flip/flop */
outb(ATC
, 0x30); outb(ATC
, 0x01);
outb(TSIDX
, 0x02); outb(TSREG
, 0x04);
outb(TSIDX
, 0x04); outb(TSREG
, 0x06);
outb(GDCIDX
, 0x04); outb(GDCREG
, 0x02);
outb(GDCIDX
, 0x05); outb(GDCREG
, 0x00);
outb(GDCIDX
, 0x06); outb(GDCREG
, 0x05); /* addr = a0000, 64kb */
for (ch
=0; ch
< 256; ch
++)
for (line
=0; line
< size
; line
++)
*((char *)atdevbase
+(segment
*0x4000)+(ch
*32)+line
) =
/* setup vga for text mode again */
inb(crtc_addr
+6); /* reset flip/flop */
outb(ATC
, 0x30); outb(ATC
, 0x0C);
outb(TSIDX
, 0x02); outb(TSREG
, 0x03);
outb(TSIDX
, 0x04); outb(TSREG
, 0x02);
outb(GDCIDX
, 0x04); outb(GDCREG
, 0x00);
outb(GDCIDX
, 0x05); outb(GDCREG
, 0x10);
if (crtc_addr
== MONO_BASE
) {
outb(GDCIDX
, 0x06); outb(GDCREG
, 0x0A); /* addr = b0000, 32kb */
outb(GDCIDX
, 0x06); outb(GDCREG
, 0x0E); /* addr = b8000, 32kb */
outb(TSIDX
, 0x01); val
= inb(TSREG
); /* unblank screen */
outb(TSIDX
, 0x01); outb(TSREG
, val
& 0xDF);
static void load_palette(void)
outb(PIXMASK
, 0xFF); /* no pixelmask */
for (i
=0x00; i
<0x300; i
++)
outb(PALDATA
, palette
[i
]);
inb(crtc_addr
+6); /* reset flip/flop */
outb(ATC
, 0x20); /* enable palette */
static void save_palette(void)
for (i
=0x00; i
<0x300; i
++)
palette
[i
] = inb(PALDATA
);
inb(crtc_addr
+6); /* reset flip/flop */
static change_winsize(struct tty
*tp
, int x
, int y
)
if (tp
->t_winsize
.ws_col
!= x
|| tp
->t_winsize
.ws_row
!= y
) {
tp
->t_winsize
.ws_col
= x
;
tp
->t_winsize
.ws_row
= y
;
pgsignal(tp
->t_pgrp
, SIGWINCH
, 1);