* 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@kmd-ac.dk) to provide:
* virtual consoles, SYSV ioctl's, ANSI emulation
* @(#)syscons.c 0.2 930402
* Modified further to provide full (updated) pccons emulation and
* hooks for init_main.c. Jordan Hubbard, 930725
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "i386/isa/isa_device.h"
#include "i386/include/pc/display.h"
#include "i386/i386/cons.h"
#include "machine/frame.h"
#define LOCK_KEY_MASK 0x00007
#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 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 0x3C0 /* attribute controller */
#define TSIDX 0x3C4 /* timing sequencer idx */
#define TSREG 0x3C5 /* timing sequencer data */
#define PIXMASK 0x3C6 /* pixel write mask */
#define PALRADR 0x3C7 /* palette read address */
#define PALWADR 0x3C8 /* palette write address */
#define PALDATA 0x3C9 /* palette data register */
#define GDCIDX 0x3CE /* graph data controller idx */
#define GDCREG 0x3CF /* graph data controller data */
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 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 posx
; /* current X position */
int posy
; /* current Y position */
int max_posx
; /* X size */
int max_posy
; /* X size */
int attr
; /* current attributes */
int std_attr
; /* normal attributes */
int rev_attr
; /* reverse attributes */
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 */
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 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 u_char shfts
= 0, ctls
= 0, alts
= 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 blank_time
= 0; /* screen saver timout value */
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 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
, u_int x
, u_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
, u_char ca
);
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");
* pick up keyboard reset return code SOS
* some keyboards / controllers hangs if this is enabled
/* while ((c=inb(KB_DATA))!=0xAA); */
int pcattach(struct isa_device
*dev
)
if (crtc_addr
== MONO_BASE
)
printf(" <%d virtual consoles>\n", NCONS
);
load_font(0, 16, font_8x16
);
load_font(1, 8, font_8x8
);
for (i
= 0; i
< NCONS
; i
++) {
scp
->scr
= (u_short
*)malloc(COL
* ROW
* 2, M_DEVBUF
, M_NOWAIT
);
scp
->std_attr
= (FG_LIGHTGREY
| BG_BLACK
) << 8;
scp
->rev_attr
= (FG_BLACK
| BG_LIGHTGREY
) << 8;
scp
->attr
= scp
->std_attr
;
scp
->smode
.mode
= VT_AUTO
;
scp
->crt_base
= scp
->crtat
= scp
->scr
;
fillw(scp
->attr
| ' ', scp
->scr
, COL
* ROW
);
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
)
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) */
blank_time
= *(int*)data
;
case CONS_80x25TEXT
: /* set 80x25 text mode */
change_winsize(tp
, scp
->max_posx
, scp
->max_posy
);
free(scp
->scr
, M_DEVBUF
);
scp
->scr
= (u_short
*)malloc(scp
->max_posx
*scp
->max_posy
*2,
case CONS_80x50TEXT
: /* set 80x50 text mode */
change_winsize(tp
, scp
->max_posx
, scp
->max_posy
);
free(scp
->scr
, M_DEVBUF
);
scp
->scr
= (u_short
*)malloc(scp
->max_posx
*scp
->max_posy
*2,
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
->std_attr
& 0x0f00)>>8;
ptr
->mv_norm
.back
= (scp
->std_attr
& 0xf000)>>12;
ptr
->mv_rev
.fore
= (scp
->rev_attr
& 0x0f00)>>8;
ptr
->mv_rev
.back
= (scp
->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 cons, allways current */
*data
= get_scr_num(scp
);
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
);
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
< 4) {
scp
->status
&= ~LOCK_KEY_MASK
;
update_leds(scp
->status
& LOCK_KEY_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 */
scp
->status
&= ~LOCK_KEY_MASK
;
scp
->status
|= (*data
& LOCK_KEY_MASK
);
update_leds(scp
->status
& LOCK_KEY_MASK
);
case KDGETLED
: /* get keyboard LED status */
*data
= scp
->status
& LOCK_KEY_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(scrmap_t
));
case PIO_SCRNMAP
: /* set output translation table */
bcopy(data
, &scr_map
, sizeof(scrmap_t
));
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(fnt8_t
));
load_font(1, 8, font_8x16
);
case GIO_FONT8x8
: /* get 8x8 dot font */
bcopy(&font_8x8
, data
, sizeof(fnt8_t
));
case PIO_FONT8x14
: /* set 8x14 dot font */
bcopy(data
, &font_8x14
, sizeof(fnt14_t
));
load_font(2, 14, font_8x14
);
case GIO_FONT8x14
: /* get 8x14 dot font */
bcopy(&font_8x14
, data
, sizeof(fnt14_t
));
case PIO_FONT8x16
: /* set 8x16 dot font */
bcopy(data
, &font_8x16
, sizeof(fnt16_t
));
load_font(0, 16, font_8x16
);
case GIO_FONT8x16
: /* get 8x16 dot font */
bcopy(&font_8x16
, data
, sizeof(fnt16_t
));
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
);
scp
->status
&= ~UNKNOWN_MODE
;
scp
->status
&= ~KBD_RAW_MODE
;
switch_scr(saved_console
);
* 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(1187500/ ((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
)
sput('\r', FG_LIGHTGREY
| BG_BLACK
);
sput(c
, FG_LIGHTGREY
| BG_BLACK
);
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 */
void scrn_saver(int test
)
if (test
&& blank_time
) {
if (time
.tv_sec
> time_stamp
+ blank_time
) {
outb(TSIDX
, 0x01); val
= inb(TSREG
);
outb(TSIDX
, 0x01); outb(TSREG
, val
| 0x20);
time_stamp
= time
.tv_sec
;
outb(TSIDX
, 0x01); val
= inb(TSREG
);
outb(TSIDX
, 0x01); outb(TSREG
, val
& 0xDF);
* alternative screen saver for cards that do not like blanking
* donated by Christoph Robitchko
static u_short cur_cursor_shape
; /* remember cursor shape */
void scrn_saver(int test
)
const char saves
[] = {"386BSD"};
static u_char
*savs
[sizeof(saves
)-1];
static u_short save_cursor
;
scr_stat
*scp
= cur_scr_stat
;
if (test
&& blank_time
) {
if (time
.tv_sec
> time_stamp
+ blank_time
) {
scp
->max_posx
* scp
->max_posy
* 2);
fillw(0x07<<8 | ' ', 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
);
f
= scp
->max_posy
* scp
->max_posx
+ 5;
outb(crtc_addr
+1, f
>> 8);
outb(crtc_addr
+1, f
& 0xff);
save_cursor
= cur_cursor_shape
;
*(savs
[sizeof(saves
)-2]) = ' ';
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
--)
time_stamp
= time
.tv_sec
;
scp
->max_posx
* scp
->max_posy
* 2);
cursor_shape((save_cursor
>> 8) & 0xff,
static void cursor_shape(int start
, int end
)
outb(crtc_addr
+1, start
& 0xFF);
outb(crtc_addr
+1, end
& 0xFF);
cur_cursor_shape
= ((start
& 0xff) << 8) | (end
& 0xff);
static void cursor_pos(void)
int pos
= cur_scr_stat
->crtat
- cur_scr_stat
->crt_base
;
if (cur_scr_stat
->status
& UNKNOWN_MODE
)
if (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
->attr
| ' ', 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 (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
& LOCK_KEY_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
, u_int x
, u_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
;
case '[': /* Start ESC [ sequence */
for (i
= scp
->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
);
scp
->crt_base
, scp
->max_posx
);
case 'c': /* Clear screen & home */
else if (scp
->esc
== 2) {
if (c
>= '0' && c
<= '9') {
if (scp
->n_par
< MAX_ESC_PAR
) {
if (scp
->last_par
!= scp
->n_par
) {
scp
->last_par
= scp
->n_par
;
scp
->par
[scp
->n_par
] = 0;
scp
->par
[scp
->n_par
] *= 10;
scp
->par
[scp
->n_par
] += c
- '0';
scp
->n_par
= scp
->last_par
+ 1;
if (scp
->n_par
< MAX_ESC_PAR
)
for (i
= scp
->n_par
; i
< MAX_ESC_PAR
; i
++)
case 'A': /* up n rows */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, scp
->posy
- n
);
case 'B': /* down n rows */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, scp
->posy
+ n
);
case 'C': /* right n columns */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
+ n
, scp
->posy
);
case 'D': /* left n columns */
n
= scp
->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
->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
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, 0, scp
->posy
- n
);
case 'f': /* System V consoles .. */
case 'H': /* Cursor move */
else if (scp
->n_par
== 2)
move_crsr(scp
, scp
->par
[1] - 1, scp
->par
[0] - 1);
case 'J': /* Clear all or part of display */
case 0: /* clear form cursor to end of display */
fillw(scp
->attr
| ' ', scp
->crtat
,
scp
->crt_base
+ scp
->max_posx
*
scp
->max_posy
- scp
->crtat
);
case 1: /* clear from beginning of display to cursor */
fillw(scp
->attr
| ' ', scp
->crt_base
,
scp
->crtat
- scp
->crt_base
);
case 2: /* clear entire display */
case 'K': /* Clear all or part of line */
case 0: /* clear form cursor to end of line */
fillw(scp
->attr
| ' ', scp
->crtat
,
scp
->max_posx
- scp
->posx
);
case 1: /* clear from beginning of line to cursor */
scp
->crtat
- (scp
->max_posx
- scp
->posx
),
(scp
->max_posx
- scp
->posx
) + 1);
case 2: /* clear entire line */
scp
->crtat
- (scp
->max_posx
- scp
->posx
),
case 'L': /* Insert n lines */
n
= scp
->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
->attr
| ' ', src
, n
* scp
->max_posx
);
case 'M': /* Delete n lines */
n
= scp
->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
->attr
| ' ', src
, n
* scp
->max_posx
);
case 'P': /* Delete n chars */
n
= scp
->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
->attr
| ' ', src
, n
);
case '@': /* Insert n chars */
n
= scp
->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
->attr
| ' ', src
, n
);
case 'S': /* scroll up n lines */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
bcopy(scp
->crt_base
+ (scp
->max_posx
* n
),
scp
->max_posx
* (scp
->max_posy
- n
) *
scp
->crt_base
+ scp
->max_posx
*
case 'T': /* scroll down n lines */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
scp
->crt_base
+ (scp
->max_posx
* n
),
scp
->max_posx
* (scp
->max_posy
- n
) *
fillw(scp
->attr
| ' ', scp
->crt_base
, scp
->max_posx
);
case 'X': /* delete n characters in line */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
fillw(scp
->attr
| ' ', scp
->crt_base
+ scp
->posx
+
((scp
->max_posx
*scp
->posy
) * sizeof(u_short
)), n
);
case 'Z': /* move n tabs backwards */
n
= scp
->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
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, n
, scp
->posy
);
case 'a': /* move cursor n columns to the right */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
+ n
, scp
->posy
);
case 'd': /* move cursor to row n */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, n
);
case 'e': /* move cursor n rows down */
n
= scp
->par
[0]; if (n
< 1) n
= 1;
move_crsr(scp
, scp
->posx
, scp
->posy
+ n
);
case 'm': /* change attribute */
case 0: /* back to normal */
scp
->attr
= scp
->std_attr
;
case 1: /* highlight (bold) */
case 4: /* highlight (underline) */
case 7: /* reverse video */
scp
->attr
= scp
->rev_attr
;
case 30: case 31: case 32: case 33: /* set fg color */
case 34: case 35: case 36: case 37:
scp
->attr
= (scp
->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
->attr
= (scp
->attr
& 0x0FFF)
| (ansi_col
[(n
- 40) & 7] << 12);
case 0: /* reset attributes */
scp
->attr
= scp
->std_attr
= FG_LIGHTGREY
<< 8;
case 1: /* set ansi background */
scp
->attr
= scp
->std_attr
=
| (ansi_col
[(scp
->par
[1])&0x0F] << 12);
case 2: /* set ansi foreground */
scp
->attr
= scp
->std_attr
=
| (ansi_col
[(scp
->par
[1])&0x0F] << 8);
case 3: /* set ansi attribute directly */
scp
->attr
= scp
->std_attr
=
(scp
->par
[1] & 0xFF) << 8;
case 5: /* set ansi reverse video background */
| (ansi_col
[(scp
->par
[1]) & 0x0F] << 12);
case 6: /* set ansi reverse video foreground */
| (ansi_col
[(scp
->par
[1]) & 0x0F] << 8);
case 7: /* set ansi reverse video directly */
scp
->rev_attr
= (scp
->par
[1] & 0xFF) << 8;
case 'z': /* switch to (virtual) console n */
else if (scp
->esc
== 3) {
if (c
>= '0' && c
<= '9') {
if (scp
->n_par
< MAX_ESC_PAR
) {
if (scp
->last_par
!= scp
->n_par
) {
scp
->last_par
= scp
->n_par
;
scp
->par
[scp
->n_par
] = 0;
scp
->par
[scp
->n_par
] *= 10;
scp
->par
[scp
->n_par
] += c
- '0';
scp
->n_par
= scp
->last_par
+ 1;
if (scp
->n_par
< MAX_ESC_PAR
)
case 'A': /* set display border color */
scp
->border
=scp
->par
[0] & 0xff;
case 'B': /* set bell pitch and duration */
scp
->bell_pitch
= scp
->par
[0];
scp
->bell_duration
= scp
->par
[1]*10;
case 'C': /* set cursor shape (start & end line) */
cursor_shape(scp
->par
[0], scp
->par
[1]);
case 'F': /* set ansi foreground */
scp
->attr
= scp
->std_attr
=
| ((scp
->par
[0] & 0x0F) << 8);
case 'G': /* set ansi background */
scp
->attr
= scp
->std_attr
=
| ((scp
->par
[0] & 0x0F) << 12);
case 'H': /* set ansi reverse video foreground */
| ((scp
->par
[0] & 0x0F) << 8);
case 'I': /* set ansi reverse video background */
| ((scp
->par
[0] & 0x0F) << 12);
#define wrtchar(scp, c) ( *scp->crtat = (c), scp->crtat++, scp->posx++ )
static void ansi_put(scr_stat
*scp
, u_char c
)
if (scp
== cur_scr_stat
)
if (scp
->status
& UNKNOWN_MODE
)
wrtchar(scp
, scp
->attr
| ' ');
case '\b': /* non-destructive backspace */
if (scp
->crtat
> scp
->crt_base
) {
scp
->posx
+= scp
->max_posx
- 1;
move_crsr(scp
, 0, scp
->posy
);
scp
->crtat
+= scp
->max_posx
;
sysbeep(scp
->bell_pitch
, scp
->bell_duration
);
/* Print only printables */
wrtchar(scp
, scp
->attr
| 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
));
scp
->crt_base
+ scp
->max_posx
* (scp
->max_posy
- 1),
scp
->crtat
-= scp
->max_posx
;
u_short
*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
* thanks to Christoph Robitchko for finding this one !!
* 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);
cons_scr_stat
[0].crtat
= crtat
;
cons_scr_stat
[0].crt_base
= Crtat
;
cons_scr_stat
[0].posx
= cursorat
% COL
;
cons_scr_stat
[0].posy
= cursorat
/ COL
;
cons_scr_stat
[0].esc
= 0;
cons_scr_stat
[0].std_attr
= (FG_LIGHTGREY
| BG_BLACK
) << 8;
cons_scr_stat
[0].rev_attr
= (FG_BLACK
| BG_LIGHTGREY
) << 8;
cons_scr_stat
[0].attr
= (FG_LIGHTGREY
| BG_BLACK
) << 8;
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;
clear_screen(&cons_scr_stat
[0]);
static void sput(u_char c
, u_char ca
)
scr_stat
*scp
= &cons_scr_stat
[0];
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
]);
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.
static u_char esc_flag
= 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 ((dt
== 83) && ctls
&& alts
)
/* Check for cntl-alt-esc */
if ((dt
== 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
)
if (dt
== 0xE0 || dt
== 0xE1) {
if ((dt
& 0x7F) >= key_map
.n_keys
)
case 0x2A: /* This may come because the keyboard keeps */
case 0x36: /* its own caps lock status, we ignore SOS */
case 0x1C: /* keypad enter key */
case 0x1D: /* right control 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: /* every thing else is ignored */
dt
= (dt
& 0x80) | modifier
;
else if (esc_flag
== (u_char
)0xE1 && ((dt
& 0x7F) == 0x1D)) {
else if (esc_flag
== 0x1D && ((dt
& 0x7F) == 0x45))
state
= (shfts
? 1 : 0 ) | (2 * (ctls
? 1 : 0)) | (4 * (alts
? 1 : 0));
key
= &key_map
.key
[dt
& 0x7F];
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 (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
&LOCK_KEY_MASK
);
if (cur_scr_stat
->status
& CLKED
)
cur_scr_stat
->status
&= ~CLKED
;
cur_scr_stat
->status
|= CLKED
;
update_leds(cur_scr_stat
->status
&LOCK_KEY_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
&LOCK_KEY_MASK
);
if (action
>= F_SCR
&& action
<= L_SCR
) {
switch_scr(action
- F_SCR
);
if (action
>= F_FN
&& action
<= L_FN
) {
/* -hv- 22-Apr-93: to make init_main more portable */
void cons_highlight(void)
scr_stat
*scp
= &cons_scr_stat
[0];
scr_stat
*scp
= &cons_scr_stat
[0];
scp
->attr
= scp
->std_attr
;
pcconsoftc
.cs_flags
|= CSF_POLLING
;
sput('>', FG_RED
| BG_BLACK
);
thechar
= (char) sgetc(0);
pcconsoftc
.cs_flags
&= ~CSF_POLLING
;
sput(thechar
, FG_RED
| BG_BLACK
);
sput(cr
, FG_RED
| BG_BLACK
);
sput(lf
, FG_RED
| BG_BLACK
);
sput(bs
, FG_RED
| BG_BLACK
);
sput(' ', FG_RED
| BG_BLACK
);
sput(bs
, FG_RED
| BG_BLACK
);
sput('^', FG_RED
| BG_BLACK
) ;
sput('D', FG_RED
| BG_BLACK
) ;
sput('\r', FG_RED
| BG_BLACK
) ;
sput('\n', FG_RED
| BG_BLACK
) ;
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
)
/* 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 */
/* (re)activate cursor */
untimeout(cursor_pos
, 0);
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);