diff options
author | dfr <dfr@FreeBSD.org> | 1998-09-17 09:38:36 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1998-09-17 09:38:36 +0000 |
commit | a1160c985757fb579a45c139d8649181ffde94dc (patch) | |
tree | b3226346dfbf2849b25075e16560d6d27ed46ae0 /sys/isa | |
parent | 271727741c72633cfbf750b45b4cb8ba1b7a9aae (diff) | |
download | FreeBSD-src-a1160c985757fb579a45c139d8649181ffde94dc.zip FreeBSD-src-a1160c985757fb579a45c139d8649181ffde94dc.tar.gz |
Merge with the latest i386 syscons.
Diffstat (limited to 'sys/isa')
-rw-r--r-- | sys/isa/scvidctl.c | 489 | ||||
-rw-r--r-- | sys/isa/syscons.c | 1841 | ||||
-rw-r--r-- | sys/isa/syscons.h | 94 | ||||
-rw-r--r-- | sys/isa/videoio.c | 1628 | ||||
-rw-r--r-- | sys/isa/videoio.h | 108 |
5 files changed, 2795 insertions, 1365 deletions
diff --git a/sys/isa/scvidctl.c b/sys/isa/scvidctl.c new file mode 100644 index 0000000..5934bdf --- /dev/null +++ b/sys/isa/scvidctl.c @@ -0,0 +1,489 @@ +/*- + * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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. The name of the author may not 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 + * SUCH DAMAGE. + * + * $Id$ + * from: i386/isa scvidctl.c,v 1.1 + */ + +#include "sc.h" +#include "opt_syscons.h" + +#if NSC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/signalvar.h> +#include <sys/tty.h> +#include <sys/kernel.h> + +#ifdef __i386__ +#include <machine/apm_bios.h> +#endif +#include <machine/console.h> + +#include <isa/videoio.h> +#include <isa/syscons.h> + +/* video ioctl */ + +extern scr_stat *cur_console; +extern u_int32_t Crtat; +extern int fonts_loaded; +extern int sc_history_size; +extern u_char palette[]; + +int +sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, + int fontsize) +{ + video_adapter_t *adp; + video_info_t info; + int error; + int s; + int i; + + if ((*biosvidsw.get_info)(scp->adp, mode, &info)) + return ENODEV; + adp = get_adapter(scp); + + /* adjust argument values */ + if (fontsize <= 0) + fontsize = info.vi_cheight; + if (fontsize < 14) { + fontsize = 8; + if (!(fonts_loaded & FONT_8)) + return EINVAL; + } else if (fontsize >= 16) { + fontsize = 16; + if (!(fonts_loaded & FONT_16)) + return EINVAL; + } else { + fontsize = 14; + if (!(fonts_loaded & FONT_14)) + return EINVAL; + } + if ((xsize <= 0) || (xsize > info.vi_width)) + xsize = info.vi_width; + if ((ysize <= 0) || (ysize > info.vi_height)) + ysize = info.vi_height; + + /* stop screen saver, etc */ + s = spltty(); + if ((error = sc_clean_up(scp))) { + splx(s); + return error; + } + + /* set up scp */ + if (scp->history != NULL) + i = imax(scp->history_size / scp->xsize + - imax(sc_history_size, scp->ysize), 0); + else + i = 0; + /* + * This is a kludge to fend off scrn_update() while we + * muck around with scp. XXX + */ + scp->status |= UNKNOWN_MODE; + scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE); + scp->mode = mode; + scp->font_size = fontsize; + scp->xsize = xsize; + scp->ysize = ysize; + scp->xpixel = scp->xsize*8; + scp->ypixel = scp->ysize*fontsize; + + /* allocate buffers */ + sc_alloc_scr_buffer(scp, TRUE, TRUE); + if (ISMOUSEAVAIL(adp->va_flags)) + sc_alloc_cut_buffer(scp, FALSE); + sc_alloc_history_buffer(scp, sc_history_size, i, FALSE); + splx(s); + + if (scp == cur_console) + set_mode(scp); + scp->status &= ~UNKNOWN_MODE; + + if (tp == NULL) + return 0; + if (tp->t_winsize.ws_col != scp->xsize + || tp->t_winsize.ws_row != scp->ysize) { + tp->t_winsize.ws_col = scp->xsize; + tp->t_winsize.ws_row = scp->ysize; + pgsignal(tp->t_pgrp, SIGWINCH, 1); + } + + return 0; +} + +int +sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) +{ + video_adapter_t *adp; + video_info_t info; + int error; + int s; + + if ((*biosvidsw.get_info)(scp->adp, mode, &info)) + return ENODEV; + adp = get_adapter(scp); + + /* stop screen saver, etc */ + s = spltty(); + if ((error = sc_clean_up(scp))) { + splx(s); + return error; + } + + /* set up scp */ + scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE); + scp->status &= ~PIXEL_MODE; + scp->mode = mode; + scp->xpixel = info.vi_width; + scp->ypixel = info.vi_height; + scp->xsize = info.vi_width/8; + scp->ysize = info.vi_height/info.vi_cheight; + scp->font_size = FONT_NONE; + /* move the mouse cursor at the center of the screen */ + sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); + splx(s); + + if (scp == cur_console) + set_mode(scp); + /* clear_graphics();*/ + scp->status &= ~UNKNOWN_MODE; + + if (tp == NULL) + return 0; + if (tp->t_winsize.ws_xpixel != scp->xpixel + || tp->t_winsize.ws_ypixel != scp->ypixel) { + tp->t_winsize.ws_xpixel = scp->xpixel; + tp->t_winsize.ws_ypixel = scp->ypixel; + pgsignal(tp->t_pgrp, SIGWINCH, 1); + } + + return 0; +} + +int +sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, + int fontsize) +{ + video_adapter_t *adp; + video_info_t info; + int error; + int s; + int i; + + if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) + return ENODEV; /* this shouldn't happen */ + adp = get_adapter(scp); + +#ifdef SC_VIDEO_DEBUG + if (scp->scr_buf != NULL) { + printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n", + scp->mode, xsize, ysize, fontsize); + } +#endif + + /* adjust argument values */ + if ((fontsize <= 0) || (fontsize == FONT_NONE)) + fontsize = info.vi_cheight; + if (fontsize < 14) { + fontsize = 8; + if (!(fonts_loaded & FONT_8)) + return EINVAL; + } else if (fontsize >= 16) { + fontsize = 16; + if (!(fonts_loaded & FONT_16)) + return EINVAL; + } else { + fontsize = 14; + if (!(fonts_loaded & FONT_14)) + return EINVAL; + } + if (xsize <= 0) + xsize = info.vi_width/8; + if (ysize <= 0) + ysize = info.vi_height/fontsize; + +#ifdef SC_VIDEO_DEBUG + if (scp->scr_buf != NULL) { + printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n", + scp->mode, xsize, ysize, fontsize); + printf("set_pixel_mode(): Crtat:%x, %dx%d, xoff:%d, yoff:%d\n", + Crtat, info.vi_width, info.vi_height, + (info.vi_width/8 - xsize)/2, + (info.vi_height/fontsize - ysize)/2); + } +#endif + + /* stop screen saver, etc */ + s = spltty(); + if ((error = sc_clean_up(scp))) { + splx(s); + return error; + } + + /* set up scp */ + if (scp->history != NULL) + i = imax(scp->history_size / scp->xsize + - imax(sc_history_size, scp->ysize), 0); + else + i = 0; + scp->status |= (UNKNOWN_MODE | PIXEL_MODE); + scp->status &= ~(GRAPHICS_MODE | MOUSE_ENABLED); + scp->xsize = xsize; + scp->ysize = ysize; + scp->font_size = fontsize; + scp->xoff = (scp->xpixel/8 - xsize)/2; + scp->yoff = (scp->ypixel/fontsize - ysize)/2; + + /* allocate buffers */ + sc_alloc_scr_buffer(scp, TRUE, TRUE); + if (ISMOUSEAVAIL(adp->va_flags)) + sc_alloc_cut_buffer(scp, FALSE); + sc_alloc_history_buffer(scp, sc_history_size, i, FALSE); + splx(s); + + /* FIXME */ + if (scp == cur_console) + memset_io(Crtat, 0, scp->xpixel*scp->ypixel/8); + + scp->status &= ~UNKNOWN_MODE; + +#ifdef SC_VIDEO_DEBUG + printf("set_pixel_mode(): status:%x\n", scp->status); +#endif + + if (tp == NULL) + return 0; + if (tp->t_winsize.ws_col != scp->xsize + || tp->t_winsize.ws_row != scp->ysize) { + tp->t_winsize.ws_col = scp->xsize; + tp->t_winsize.ws_row = scp->ysize; + pgsignal(tp->t_pgrp, SIGWINCH, 1); + } + + return 0; +} + +int +sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + scr_stat *scp; + video_adapter_t *adp; + int error; + int s; + + scp = sc_get_scr_stat(tp->t_dev); + + switch (cmd) { + + case CONS_CURRENT: /* get current adapter type */ + adp = get_adapter(scp); + *(int *)data = adp->va_type; + return 0; + + case CONS_CURRENTADP: /* get current adapter index */ + *(int *)data = scp->adp; + return 0; + + case CONS_ADPINFO: /* adapter information */ + adp = (*biosvidsw.adapter)(((video_adapter_t *)data)->va_index); + if (adp == NULL) + return ENODEV; + bcopy(adp, data, sizeof(*adp)); + return 0; + + case CONS_GET: /* get current video mode */ + *(int *)data = scp->mode; + return 0; + + case CONS_MODEINFO: /* get mode information */ + return ((*biosvidsw.get_info)(scp->adp, + ((video_info_t *)data)->vi_mode, (video_info_t *)data) + ? ENODEV : 0); + + case CONS_FINDMODE: /* find a matching video mode */ + return ((*biosvidsw.query_mode)(scp->adp, (video_info_t *)data) + ? ENODEV : 0); + + case CONS_SETWINORG: + return ((*biosvidsw.set_win_org)(scp->adp, *(u_int *)data) + ? ENODEV : 0); + + /* VGA TEXT MODES */ + case SW_VGA_C40x25: + case SW_VGA_C80x25: case SW_VGA_M80x25: + case SW_VGA_C80x30: case SW_VGA_M80x30: + case SW_VGA_C80x50: case SW_VGA_M80x50: + case SW_VGA_C80x60: case SW_VGA_M80x60: + case SW_B40x25: case SW_C40x25: + case SW_B80x25: case SW_C80x25: + case SW_ENH_B40x25: case SW_ENH_C40x25: + case SW_ENH_B80x25: case SW_ENH_C80x25: + case SW_ENH_B80x43: case SW_ENH_C80x43: + case SW_EGAMONO80x25: + adp = get_adapter(scp); + if (!(adp->va_flags & V_ADP_MODECHANGE)) + return ENODEV; + return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0); + + /* GRAPHICS MODES */ + case SW_BG320: case SW_BG640: + case SW_CG320: case SW_CG320_D: case SW_CG640_E: + case SW_CG640x350: case SW_ENH_CG640: + case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: + case SW_VGA_MODEX: + adp = get_adapter(scp); + if (!(adp->va_flags & V_ADP_MODECHANGE)) + return ENODEV; + return sc_set_graphics_mode(scp, tp, cmd & 0xff); + + case KDSETMODE: /* set current mode of this (virtual) console */ + switch (*data) { + case KD_TEXT: /* switch to TEXT (known) mode */ + /* + * If scp->mode is of graphics modes, we don't know which + * text mode to switch back to... + */ + if (scp->status & GRAPHICS_MODE) + return EINVAL; + /* restore fonts & palette ! */ +#if 0 + adp = get_adapter(scp); + if (ISFONTAVAIL(adp->va_flags) + && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) + /* + * FONT KLUDGE + * Don't load fonts for now... XXX + */ + if (fonts_loaded & FONT_8) + copy_font(scp, LOAD, 8, font_8); + if (fonts_loaded & FONT_14) + copy_font(scp, LOAD, 14, font_14); + if (fonts_loaded & FONT_16) + copy_font(scp, LOAD, 16, font_16); + } +#endif + load_palette(scp, palette); + + /* move hardware cursor out of the way */ + (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); + + /* FALL THROUGH */ + + case KD_TEXT1: /* switch to TEXT (known) mode */ + /* + * If scp->mode is of graphics modes, we don't know which + * text/pixel mode to switch back to... + */ + if (scp->status & GRAPHICS_MODE) + return EINVAL; + s = spltty(); + if ((error = sc_clean_up(scp))) { + splx(s); + return error; + } + scp->status |= UNKNOWN_MODE; + splx(s); + /* no restore fonts & palette */ + if (scp == cur_console) { + set_mode(scp); + /* FIXME */ + if (scp->status & PIXEL_MODE) + memset_io(Crtat, 0, scp->xpixel*scp->ypixel/8); + } + sc_clear_screen(scp); + scp->status &= ~UNKNOWN_MODE; + return 0; + + case KD_PIXEL: /* pixel (raster) display */ + if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) + return EINVAL; + if (!(scp->status & PIXEL_MODE)) + return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, + scp->font_size); + s = spltty(); + if ((error = sc_clean_up(scp))) { + splx(s); + return error; + } + scp->status |= (UNKNOWN_MODE | PIXEL_MODE); + splx(s); + if (scp == cur_console) { + set_mode(scp); + load_palette(scp, palette); + /* FIXME */ + memset_io(Crtat, 0, scp->xpixel*scp->ypixel/8); + } + sc_clear_screen(scp); + scp->status &= ~UNKNOWN_MODE; + return 0; + + case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ + s = spltty(); + if ((error = sc_clean_up(scp))) { + splx(s); + return error; + } + scp->status |= UNKNOWN_MODE; + splx(s); + return 0; + + default: + return EINVAL; + } + /* NOT REACHED */ + + case KDRASTER: /* set pixel (raster) display mode */ + if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) + return ENODEV; + return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], + ((int *)data)[2]); + + case KDGETMODE: /* get current mode of this (virtual) console */ + /* + * From the user program's point of view, KD_PIXEL is the same + * as KD_TEXT... + */ + *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; + return 0; + + case KDSBORDER: /* set border color of this (virtual) console */ + scp->border = *data; + if (scp == cur_console) + set_border(cur_console, scp->border); + return 0; + } + + return ENOIOCTL; +} + +#endif /* NSC > 0 */ diff --git a/sys/isa/syscons.c b/sys/isa/syscons.c index 311a63c..6d9f7c9 100644 --- a/sys/isa/syscons.c +++ b/sys/isa/syscons.c @@ -1,18 +1,18 @@ /*- - * Copyright (c) 1992-1997 Søren Schmidt + * Copyright (c) 1992-1998 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. * 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. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission + * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -25,8 +25,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ - * from: i386/isa syscons.c,v 1.272 + * $Id: syscons.c,v 1.273 1998/08/06 09:15:53 dfr Exp $ + * from: i386/isa syscons.c,v 1.278 */ #include "sc.h" @@ -35,6 +35,10 @@ #include "opt_ddb.h" #include "opt_devfs.h" +#ifdef __i386__ +#include "opt_vesa.h" +#include "opt_vm86.h" +#endif #include "opt_syscons.h" #if NSC > 0 @@ -54,7 +58,6 @@ #include <sys/devfsext.h> #endif -#include <machine/bootinfo.h> #include <machine/clock.h> #include <machine/cons.h> #include <machine/console.h> @@ -63,6 +66,7 @@ #include <machine/psl.h> #include <machine/frame.h> #include <machine/pc/display.h> +#include <machine/pc/vesa.h> /* #include <machine/apm_bios.h> */ /* #include <machine/random.h> */ @@ -75,6 +79,7 @@ #include <isa/timerreg.h> #include <isa/kbdtables.h> #include <isa/kbdio.h> +#include <isa/videoio.h> #include <isa/syscons.h> #if !defined(MAXCONS) @@ -101,11 +106,6 @@ #define COLD 0 #define WARM 1 -#define VESA_MODE(x) ((x) >= M_VESA_BASE) - -#define MODE_MAP_SIZE (M_VGA_CG320 + 1) -#define MODE_PARAM_SIZE 64 - #define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ #define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ @@ -143,7 +143,6 @@ static scr_stat main_console; static scr_stat *console[MAXCONS]; #ifdef DEVFS static void *sc_devfs_token[MAXCONS]; -static void *sc_vga_devfs_token; static void *sc_mouse_devfs_token; static void *sc_console_devfs_token; #endif @@ -165,6 +164,7 @@ static int blinkrate = 0; u_int crtc_addr = MONO_BASE; char crtc_type = KD_MONO; char crtc_vga = FALSE; +static int adp_flags = 0; static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; static u_char accents = 0; static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; @@ -178,7 +178,7 @@ static int run_scrn_saver = FALSE; /* should run the saver? */ static int scrn_idle = FALSE; /* about to run the saver */ u_char scr_map[256]; u_char scr_rmap[256]; - char *video_mode_ptr = NULL; +static int initial_video_mode; /* initial video mode # */ static int bios_video_mode; /* video mode # set by BIOS */ int fonts_loaded = 0 #ifdef STD8X16FONT @@ -186,19 +186,15 @@ static int bios_video_mode; /* video mode # set by BIOS */ #endif ; - char font_8[256*8]; - char font_14[256*14]; + u_char font_8[256*8]; + u_char font_14[256*14]; #ifdef STD8X16FONT extern #endif - unsigned char font_16[256*16]; - char palette[256*3]; -static char *mode_map[MODE_MAP_SIZE]; -static char vgaregs[MODE_PARAM_SIZE]; -static char vgaregs2[MODE_PARAM_SIZE]; -static int rows_offset = 1; -static char *cut_buffer; -static int cut_buffer_size; + u_char font_16[256*16]; + u_char palette[256*3]; +static u_char *cut_buffer = NULL; +static int cut_buffer_size = 0; static int mouse_level = 0; /* sysmouse protocol level */ static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; static u_short mouse_and_mask[16] = { @@ -214,13 +210,14 @@ static u_short mouse_or_mask[16] = { 0x0000, 0x0000, 0x0000, 0x0000 }; -static int extra_history_size = + int sc_history_size = SC_HISTORY_SIZE; +static int extra_history_size = SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; static void none_saver(int blank) { } static void (*current_saver)(int blank) = none_saver; static void (*default_saver)(int blank) = none_saver; -int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, + int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) = NULL; static int sticky_splash = FALSE; @@ -239,8 +236,6 @@ static struct tty sccons[MAXCONS+2]; #endif #define SC_MOUSE 128 #define SC_CONSOLE 255 -#define MONO_BUF 0xB0000 -#define CGA_BUF 0xB8000 u_int32_t Crtat; static const int nsccons = MAXCONS+2; @@ -249,9 +244,6 @@ static const int nsccons = MAXCONS+2; + (offset)) % (scp->history_size))) #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) -/* this should really be in `rtc.h' */ -#define RTC_EQUIPMENT 0x14 - /* prototypes */ static int scattach(device_t dev); static int scparam(struct tty *tp, struct termios *t); @@ -263,30 +255,26 @@ static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); static void scshutdown(int howto, void *arg); -static void map_mode_table(char *map[], char *table, int max); -static int map_mode_num(int mode); -static char *get_mode_param(scr_stat *scp, int mode); static u_int scgetc(u_int flags); #define SCGETC_CN 1 #define SCGETC_NONBLOCK 2 static void sccnupdate(scr_stat *scp); -static scr_stat *get_scr_stat(dev_t dev); static scr_stat *alloc_scp(void); static void init_scp(scr_stat *scp); static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); static int get_scr_num(void); static timeout_t scrn_timer; static void scrn_update(scr_stat *scp, int show_cursor); +static void scrn_saver(void (*saver)(int), int blank); static void stop_scrn_saver(void (*saver)(int)); static int wait_scrn_saver_stop(void); -static void clear_screen(scr_stat *scp); static int switch_scr(scr_stat *scp, u_int next_scr); static void exchange_scr(void); -static void move_crsr(scr_stat *scp, int x, int y); static void scan_esc(scr_stat *scp, u_char c); +static void ansi_put(scr_stat *scp, u_char *buf, int len); static void draw_cursor_image(scr_stat *scp); static void remove_cursor_image(scr_stat *scp); -static void ansi_put(scr_stat *scp, u_char *buf, int len); +static void move_crsr(scr_stat *scp, int x, int y); static u_char *get_fstr(u_int c, u_int *len); static void history_to_screen(scr_stat *scp); static int history_up_line(scr_stat *scp); @@ -294,16 +282,6 @@ static int history_down_line(scr_stat *scp); static int mask2attr(struct term_stat *term); static void set_keyboard(int command, int data); static void update_leds(int which); -static void set_vgaregs(char *modetable); -static void read_vgaregs(char *buf); -#define COMP_IDENTICAL 0 -#define COMP_SIMILAR 1 -#define COMP_DIFFERENT 2 -static int comp_vgaregs(u_char *buf1, u_char *buf2); -static void dump_vgaregs(u_char *buf); -#define PARAM_BUFSIZE 6 -static void set_font_mode(u_char *buf); -static void set_normal_mode(u_char *buf); static void set_destructive_cursor(scr_stat *scp); static void set_mouse_pos(scr_stat *scp); static int skip_spc_right(scr_stat *scp, u_short *p); @@ -319,12 +297,11 @@ static void draw_mouse_image(scr_stat *scp); static void remove_mouse_image(scr_stat *scp); static void draw_cutmarking(scr_stat *scp); static void remove_cutmarking(scr_stat *scp); -static void save_palette(void); static void do_bell(scr_stat *scp, int pitch, int duration); static timeout_t blink_screen; #ifdef SC_SPLASH_SCREEN -static void scsplash_init(void); -static void scsplash(int show); +static void scsplash_init(scr_stat *scp); +static void scsplash_saver(int show); #define scsplash_stick(stick) (sticky_splash = (stick)) #else #define scsplash_stick(stick) @@ -352,14 +329,17 @@ static d_close_t scclose; static d_read_t scread; static d_write_t scwrite; static d_ioctl_t scioctl; -static d_devtotty_t scdevtotty; + d_devtotty_t scdevtotty; static d_mmap_t scmmap; -#define CDEV_MAJOR 12 -static struct cdevsw scdevsw = { +#define CDEV_MAJOR 12 +static struct cdevsw sc_cdevsw = { scopen, scclose, scread, scwrite, scioctl, nullstop, noreset, scdevtotty, - ttpoll, scmmap, nostrategy, "sc", NULL, -1 }; + ttpoll, scmmap, nostrategy, "sc", + NULL, -1, nodump, nopsize, + D_TTY, +}; /* * These functions need to be before calls to them so they can be inlined. @@ -391,7 +371,7 @@ draw_cursor_image(scr_stat *scp) u_int32_t ptr = Crtat + 2*(scp->cursor_pos - scp->scr_buf); u_short prev_image; - if (VESA_MODE(scp->mode)) { + if (ISPIXELSC(scp)) { sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, scp->cursor_pos - scp->scr_buf, 1); return; @@ -443,7 +423,7 @@ draw_cursor_image(scr_stat *scp) static void remove_cursor_image(scr_stat *scp) { - if (VESA_MODE(scp->mode)) + if (ISPIXELSC(scp)) sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 0); else @@ -474,6 +454,12 @@ scprobe(device_t dev) printf("sc%d: no video adapter is found.\n", device_get_unit(dev)); return (0); } + (*biosvidsw.diag)(bootverbose); +#if defined(VESA) && defined(VM86) + if (vesa_load()) + return FALSE; + (*biosvidsw.diag)(bootverbose); +#endif sc_port = isa_get_port(dev); isa_set_portsize(dev, IO_KBDSIZE); @@ -487,106 +473,24 @@ scprobe(device_t dev) static int scvidprobe(int unit, int flags) { - /* - * XXX don't try to `printf' anything here, the console may not have - * been configured yet. - */ - u_int32_t cp; - u_short was; - u_int pa; - u_int segoff; + video_adapter_t *adp; /* do this test only once */ if (init_done != COLD) - return (Crtat != 0); - - /* - * Finish defaulting crtc variables for a mono screen. Crtat is a - * bogus common variable so that it can be shared with pcvt, so it - * can't be statically initialized. XXX. - */ - Crtat = MONO_BUF; - crtc_type = KD_MONO; - /* If CGA memory seems to work, switch to color. */ - cp = CGA_BUF; - was = readw(cp); - writew(cp, 0xA55A); -#ifdef __i386__ - bios_video_mode = *(u_char *)pa_to_va(0x449); - if (bootinfo.bi_vesa == 0x102) { - bios_video_mode = bootinfo.bi_vesa; - Crtat = 0xA0000; - crtc_addr = COLOR_BASE; - crtc_type = KD_VGA; - memset_io(Crtat, 0, 800*600/8); - } else -#endif - if (readw(cp)) { - Crtat = CGA_BUF; - crtc_addr = COLOR_BASE; - crtc_type = KD_CGA; - } else { - cp = Crtat; - was = readw(cp); - writew(cp, 0xA55A); - if (readw(cp) != 0xA55A) { - /* no screen at all, bail out */ - Crtat = 0; - return FALSE; - } - } - writew(cp, was); + return (crtc_type != -1); - if (!VESA_MODE(bios_video_mode)) { -#ifdef __i386__ - /* - * Check rtc and BIOS date area. - * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy - * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are - * zeros for EGA and VGA. However, the EGA/VGA BIOS will set - * these bits in BIOSDATA_EQUIPMENT according to the monitor - * type detected. - */ - switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ - case 0: /* EGA/VGA, or nothing */ - crtc_type = KD_EGA; - /* the color adapter may be in the 40x25 mode... XXX */ - break; - case 1: /* CGA 40x25 */ - /* switch to the 80x25 mode? XXX */ - /* FALL THROUGH */ - case 2: /* CGA 80x25 */ - /* `crtc_type' has already been set... */ - /* crtc_type = KD_CGA; */ - break; - case 3: /* MDA */ - /* `crtc_type' has already been set... */ - /* crtc_type = KD_MONO; */ - break; - } -#endif + if ((*biosvidsw.init)() <= 0) + return FALSE; + if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL) + return FALSE; - /* is this a VGA or higher ? */ - outb(crtc_addr, 7); - if (inb(crtc_addr) == 7) { - - crtc_type = KD_VGA; - crtc_vga = TRUE; - read_vgaregs(vgaregs); - -#ifdef __i386__ - /* Get the BIOS video mode pointer */ - segoff = readl(0x4a8); - pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff); - if (ISMAPPED(pa, sizeof(u_int))) { - segoff = readl(pa); - pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff); - if (ISMAPPED(pa, MODE_PARAM_SIZE)) - video_mode_ptr = (char *)pa_to_va(pa); - } -#endif - } - } + crtc_type = adp->va_type; + crtc_vga = (crtc_type == KD_VGA); + crtc_addr = adp->va_crtc_addr; + Crtat = adp->va_window; + adp_flags = adp->va_flags; + initial_video_mode = adp->va_initial_mode; + bios_video_mode = adp->va_initial_bios_mode; return TRUE; } @@ -784,92 +688,57 @@ static int scattach(device_t dev) { scr_stat *scp; + video_info_t info; dev_t cdev = makedev(CDEV_MAJOR, 0); - char *p; - void *ih; #ifdef DEVFS int vc; #endif + void *ih; scinit(); flags = isa_get_flags(dev); - if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode)) + if (!ISFONTAVAIL(adp_flags)) flags &= ~CHAR_CURSOR; scp = console[0]; - if (crtc_type == KD_VGA) { - cut_buffer_size = scp->xsize * scp->ysize + 1; - cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT); - if (cut_buffer != NULL) - cut_buffer[0] = '\0'; - } - - scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), - M_DEVBUF, M_NOWAIT); - /* copy temporary buffer to final buffer */ - bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); + scp->scr_buf = NULL; + sc_alloc_scr_buffer(scp, FALSE, FALSE); + bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short)); - scp->cursor_pos = scp->cursor_oldpos = - scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; - scp->mouse_pos = scp->mouse_oldpos = - scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + - scp->mouse_xpos/8); + /* cut buffer is available only when the mouse pointer is used */ + if (ISMOUSEAVAIL(adp_flags)) + sc_alloc_cut_buffer(scp, FALSE); /* initialize history buffer & pointers */ - scp->history_head = scp->history_pos = - (u_short *)malloc(scp->history_size*sizeof(u_short), - M_DEVBUF, M_NOWAIT); - if (scp->history_head != NULL) - bzero(scp->history_head, scp->history_size*sizeof(u_short)); - scp->history = scp->history_head; + sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); + +#if defined(VESA) && defined(VM86) + if ((flags & VESA800X600) + && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { + sc_set_graphics_mode(scp, NULL, M_VESA_800x600); + sc_set_pixel_mode(scp, NULL, COL, ROW, 16); + initial_video_mode = M_VESA_800x600; + } +#endif /* VESA && VM86 */ /* initialize cursor stuff */ - if (!(scp->status & UNKNOWN_MODE)) + if (!ISGRAPHSC(scp)) draw_cursor_image(scp); /* get screen update going */ - scrn_timer((void*)TRUE); + scrn_timer((void *)TRUE); update_leds(scp->status); - if ((crtc_type == KD_VGA) && bootverbose) { - printf("sc%d: BIOS video mode:%d\n", device_get_unit(dev), bios_video_mode); - printf("sc%d: VGA registers upon power-up\n", device_get_unit(dev)); - dump_vgaregs(vgaregs); - printf("sc%d: video mode:%d\n", device_get_unit(dev), scp->mode); - printf("sc%d: VGA registers in BIOS for mode:%d\n", - device_get_unit(dev), scp->mode); - dump_vgaregs(vgaregs2); - p = get_mode_param(scp, scp->mode); - if (p != NULL) { - printf("sc%d: VGA registers to be used for mode:%d\n", - device_get_unit(dev), scp->mode); - dump_vgaregs(p); - } - printf("sc%d: rows_offset:%d\n", device_get_unit(dev), rows_offset); - } - if ((crtc_type == KD_VGA) && !VESA_MODE(bios_video_mode) - && (video_mode_ptr == NULL)) - printf("sc%d: WARNING: video mode switching is only partially supported\n", - device_get_unit(dev)); - printf("sc%d: ", device_get_unit(dev)); switch(crtc_type) { case KD_VGA: - if (VESA_MODE(bios_video_mode)) - printf("Graphics display (VESA mode = 0x%x)", bios_video_mode); - else if (crtc_addr == MONO_BASE) - printf("VGA mono"); - else - printf("VGA color"); + printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); break; case KD_EGA: - if (crtc_addr == MONO_BASE) - printf("EGA mono"); - else - printf("EGA color"); + printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); break; case KD_CGA: printf("CGA"); @@ -877,7 +746,7 @@ scattach(device_t dev) case KD_MONO: case KD_HERCULES: default: - printf("MDA/hercules"); + printf("MDA/Hercules"); break; } printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); @@ -894,12 +763,11 @@ scattach(device_t dev) #ifdef DEVFS for (vc = 0; vc < MAXCONS; vc++) - sc_devfs_token[vc] = devfs_add_devswf(&scdevsw, vc, DV_CHR, + sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR, UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc); - sc_vga_devfs_token = devfs_link(sc_devfs_token[0], "vga"); - sc_mouse_devfs_token = devfs_add_devswf(&scdevsw, SC_MOUSE, DV_CHR, + sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR, UID_ROOT, GID_WHEEL, 0600, "sysmouse"); - sc_console_devfs_token = devfs_add_devswf(&scdevsw, SC_CONSOLE, DV_CHR, + sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR, UID_ROOT, GID_WHEEL, 0600, "consolectl"); #endif @@ -911,7 +779,6 @@ scattach(device_t dev) BUS_CONNECT_INTR(device_get_parent(dev), ih); - return 0; } @@ -953,7 +820,6 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; scparam(tp, &tp->t_termios); - ttsetwater(tp); (*linesw[tp->t_line].l_modem)(tp, 1); if (minor(dev) == SC_MOUSE) mouse_level = 0; /* XXX */ @@ -963,6 +829,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) return(EBUSY); if (minor(dev) < MAXCONS && !console[minor(dev)]) { console[minor(dev)] = alloc_scp(); + if (ISGRAPHSC(console[minor(dev)])) + sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16); } if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { tp->t_winsize.ws_col = console[minor(dev)]->xsize; @@ -980,7 +848,7 @@ scclose(dev_t dev, int flag, int mode, struct proc *p) if (!tp) return(ENXIO); if (minor(dev) < MAXCONS) { - scp = get_scr_stat(tp->t_dev); + scp = sc_get_scr_stat(tp->t_dev); if (scp->status & SWITCH_WAIT_ACQ) wakeup((caddr_t)&scp->smode); #if not_yet_done @@ -994,9 +862,9 @@ scclose(dev_t dev, int flag, int mode, struct proc *p) if (scp->history != NULL) { free(scp->history, M_DEVBUF); if (scp->history_size / scp->xsize - > imax(SC_HISTORY_SIZE, scp->ysize)) + > imax(sc_history_size, scp->ysize)) extra_history_size += scp->history_size / scp->xsize - - imax(SC_HISTORY_SIZE, scp->ysize); + - imax(sc_history_size, scp->ysize); } free(scp, M_DEVBUF); console[minor(dev)] = NULL; @@ -1075,10 +943,17 @@ scintr(void *arg) } } +#if 0 if (cur_console->status & MOUSE_ENABLED) { cur_console->status &= ~MOUSE_VISIBLE; remove_mouse_image(cur_console); } +#else + if (cur_console->status & MOUSE_VISIBLE) { + remove_mouse_image(cur_console); + cur_console->status &= ~MOUSE_VISIBLE; + } +#endif } static int @@ -1097,21 +972,25 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) u_int i; struct tty *tp; scr_stat *scp; - u_short *usp; - char *mp; + video_adapter_t *adp; int s; tp = scdevtotty(dev); if (!tp) return ENXIO; - scp = get_scr_stat(tp->t_dev); + scp = sc_get_scr_stat(tp->t_dev); /* If there is a user_ioctl function call that first */ if (sc_user_ioctl) { - if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p)) + error = (*sc_user_ioctl)(dev, cmd, data, flag, p); + if (error != ENOIOCTL) return error; } + error = sc_vid_ioctl(tp, cmd, data, flag, p); + if (error != ENOIOCTL) + return error; + switch (cmd) { /* process console hardware related ioctl's */ case GIO_ATTR: /* get current attributes */ @@ -1119,18 +998,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case GIO_COLOR: /* is this a color console ? */ - if (crtc_addr == COLOR_BASE) - *(int*)data = 1; - else - *(int*)data = 0; - return 0; - - case CONS_CURRENT: /* get current adapter type */ - *(int *)data = crtc_type; - return 0; - - case CONS_GET: /* get current video mode */ - *(int*)data = scp->mode; + *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0; return 0; case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ @@ -1148,7 +1016,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) else flags &= ~BLINK_CURSOR; if ((*(int*)data) & 0x02) { - if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode)) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; flags |= CHAR_CURSOR; } else @@ -1157,7 +1025,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * The cursor shape is global property; all virtual consoles * are affected. Update the cursor in the current console... */ - if (!(cur_console->status & UNKNOWN_MODE)) { + if (!ISGRAPHSC(cur_console)) { remove_cursor_image(cur_console); if (flags & CHAR_CURSOR) set_destructive_cursor(cur_console); @@ -1184,37 +1052,22 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) lines = imax(*(int *)data, scp->ysize); lines0 = (scp->history != NULL) ? scp->history_size / scp->xsize : scp->ysize; + if (lines0 > imax(sc_history_size, scp->ysize)) + i = lines0 - imax(sc_history_size, scp->ysize); + else + i = 0; /* * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE * lines or scp->ysize lines, whichever is larger. A value * greater than that is allowed, subject to extra_history_size. */ - if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size) - return EINVAL; + if (lines > imax(sc_history_size, scp->ysize)) + if (lines - imax(sc_history_size, scp->ysize) > + extra_history_size + i) + return EINVAL; if (cur_console->status & BUFFER_SAVED) return EBUSY; - usp = scp->history; - scp->history = NULL; - if (usp != NULL) - free(usp, M_DEVBUF); - scp->history_size = lines * scp->xsize; - /* - * extra_history_size += - * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ? - * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; - * extra_history_size -= - * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ? - * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; - * lines0 >= ysize && lines >= ysize... Hey, the above can be - * reduced to the following... - */ - extra_history_size += - imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE); - usp = (u_short *)malloc(scp->history_size * sizeof(u_short), - M_DEVBUF, M_WAITOK); - bzero(usp, scp->history_size * sizeof(u_short)); - scp->history_head = scp->history_pos = usp; - scp->history = usp; + sc_alloc_history_buffer(scp, lines, i, TRUE); return 0; } else @@ -1238,7 +1091,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) mouse_info_t *mouse = (mouse_info_t*)data; mouse_info_t buf; - if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode)) + /* FIXME: */ + if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags)) return ENODEV; if (cmd == OLD_CONS_MOUSECTL) { @@ -1287,7 +1141,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case MOUSE_SHOW: - if (!(scp->status & MOUSE_ENABLED)) { + if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) { scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); scp->mouse_oldpos = scp->mouse_pos; mark_all(scp); @@ -1298,7 +1152,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) break; case MOUSE_HIDE: - if (scp->status & MOUSE_ENABLED) { + if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) { scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); mark_all(scp); return 0; @@ -1343,7 +1197,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) if (mouse_status.flags == 0) return 0; - if (cur_console->status & MOUSE_ENABLED) + if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) cur_console->status |= MOUSE_VISIBLE; if ((MOUSE_TTY)->t_state & TS_ISOPEN) { @@ -1388,7 +1242,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) { /* process button presses */ if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && - !(cur_console->status & UNKNOWN_MODE)) { + ISTEXTSC(cur_console)) { cur_console->mouse_buttons = mouse->u.data.buttons; if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) mouse_cut_start(cur_console); @@ -1425,7 +1279,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) if (mouse_status.flags == 0) return 0; - if (cur_console->status & MOUSE_ENABLED) + if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) cur_console->status |= MOUSE_VISIBLE; if ((MOUSE_TTY)->t_state & TS_ISOPEN) { @@ -1454,7 +1308,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) break; } - if ((cur_console->status & UNKNOWN_MODE) || (cut_buffer == NULL)) + if (!ISTEXTSC(cur_console) || (cut_buffer == NULL)) break; switch (mouse->u.event.id) { @@ -1634,18 +1488,41 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case CONS_IDLE: /* see if the screen has been idle */ - *(int *)data = (scrn_idle && !(cur_console->status & UNKNOWN_MODE)); + /* + * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE, + * the user process may have been writing something on the + * screen and syscons is not aware of it. Declare the screen + * is NOT idle if it is in one of these modes. But there is + * an exception to it; if a screen saver is running in the + * graphics mode in the current screen, we should say that the + * screen has been idle. + */ + *(int *)data = scrn_idle + && (!ISGRAPHSC(cur_console) + || (cur_console->status & SAVER_RUNNING)); return 0; case CONS_SAVERMODE: /* set saver mode */ switch(*(int *)data) { case CONS_USR_SAVER: - /* if a LKM screen saver is running, it will eventually stop... */ + /* if a LKM screen saver is running, stop it first. */ + scsplash_stick(FALSE); saver_mode = *(int *)data; + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + scp->status |= SAVER_RUNNING; scsplash_stick(TRUE); + splx(s); break; case CONS_LKM_SAVER: + s = spltty(); + if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING)) + scp->status &= ~SAVER_RUNNING; saver_mode = *(int *)data; + splx(s); break; default: return EINVAL; @@ -1664,226 +1541,6 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) splx(s); return 0; - /* VGA TEXT MODES */ - case SW_VGA_C40x25: - case SW_VGA_C80x25: case SW_VGA_M80x25: - case SW_VGA_C80x30: case SW_VGA_M80x30: - case SW_VGA_C80x50: case SW_VGA_M80x50: - case SW_VGA_C80x60: case SW_VGA_M80x60: - case SW_B40x25: case SW_C40x25: - case SW_B80x25: case SW_C80x25: - case SW_ENH_B40x25: case SW_ENH_C40x25: - case SW_ENH_B80x25: case SW_ENH_C80x25: - case SW_ENH_B80x43: case SW_ENH_C80x43: - case SW_EGAMONO80x25: - - if (crtc_type != KD_VGA) - return ENODEV; - mp = get_mode_param(scp, cmd & 0xff); - if (mp == NULL) - return ENODEV; - - s = spltty(); - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } - - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - if (scp->history != NULL) - i = imax(scp->history_size / scp->xsize - - imax(SC_HISTORY_SIZE, scp->ysize), 0); - else - i = 0; - switch (cmd & 0xff) { - case M_VGA_C80x60: case M_VGA_M80x60: - if (!(fonts_loaded & FONT_8)) { - splx(s); - return EINVAL; - } - /* - * This is a kludge to fend off scrn_update() while we - * muck around with scp. XXX - */ - scp->status |= UNKNOWN_MODE; - scp->xsize = 80; - scp->ysize = 60; - scp->font_size = 8; - break; - case M_VGA_C80x50: case M_VGA_M80x50: - if (!(fonts_loaded & FONT_8)) { - splx(s); - return EINVAL; - } - scp->status |= UNKNOWN_MODE; - scp->xsize = 80; - scp->ysize = 50; - scp->font_size = 8; - break; - case M_ENH_B80x43: case M_ENH_C80x43: - if (!(fonts_loaded & FONT_8)) { - splx(s); - return EINVAL; - } - scp->status |= UNKNOWN_MODE; - scp->xsize = 80; - scp->ysize = 43; - scp->font_size = 8; - break; - case M_VGA_C80x30: case M_VGA_M80x30: - scp->status |= UNKNOWN_MODE; - scp->xsize = 80; - scp->ysize = 30; - scp->font_size = mp[2]; - break; - case M_ENH_C40x25: case M_ENH_B40x25: - case M_ENH_C80x25: case M_ENH_B80x25: - case M_EGAMONO80x25: - if (!(fonts_loaded & FONT_14)) { - splx(s); - return EINVAL; - } - /* FALL THROUGH */ - default: - if ((cmd & 0xff) > M_VGA_CG320) { - splx(s); - return EINVAL; - } - scp->status |= UNKNOWN_MODE; - scp->xsize = mp[0]; - scp->ysize = mp[1] + rows_offset; - scp->font_size = mp[2]; - break; - } - - scp->mode = cmd & 0xff; - scp->xpixel = scp->xsize * 8; - scp->ypixel = scp->ysize * scp->font_size; - free(scp->scr_buf, M_DEVBUF); - scp->scr_buf = (u_short *) - malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK); - /* move the text cursor to the home position */ - move_crsr(scp, 0, 0); - /* move the mouse cursor at the center of the screen */ - scp->mouse_xpos = scp->xpixel / 2; - scp->mouse_ypos = scp->ypixel / 2; - scp->mouse_pos = scp->mouse_oldpos = - scp->scr_buf + (scp->mouse_ypos / scp->font_size) * scp->xsize - + scp->mouse_xpos / 8; - /* allocate a larger cut buffer if necessary */ - if ((cut_buffer == NULL) - || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { - if (cut_buffer != NULL) - free(cut_buffer, M_DEVBUF); - cut_buffer_size = scp->xsize * scp->ysize + 1; - cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT); - if (cut_buffer != NULL) - cut_buffer[0] = '\0'; - } - splx(s); - - usp = scp->history; - scp->history = NULL; - if (usp != NULL) { - free(usp, M_DEVBUF); - extra_history_size += i; - } - scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; - usp = (u_short *)malloc(scp->history_size * sizeof(u_short), - M_DEVBUF, M_NOWAIT); - if (usp != NULL) - bzero(usp, scp->history_size * sizeof(u_short)); - scp->history_head = scp->history_pos = usp; - scp->history = usp; - if (scp == cur_console) - set_mode(scp); - clear_screen(scp); - scp->status &= ~UNKNOWN_MODE; - - if (tp->t_winsize.ws_col != scp->xsize - || tp->t_winsize.ws_row != scp->ysize) { - tp->t_winsize.ws_col = scp->xsize; - tp->t_winsize.ws_row = scp->ysize; - pgsignal(tp->t_pgrp, SIGWINCH, 1); - } - return 0; - - /* GRAPHICS MODES */ - case SW_BG320: case SW_BG640: - case SW_CG320: case SW_CG320_D: case SW_CG640_E: - case SW_CG640x350: case SW_ENH_CG640: - case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: - - if (crtc_type != KD_VGA) - return ENODEV; - mp = get_mode_param(scp, cmd & 0xff); - if (mp == NULL) - return ENODEV; - - s = spltty(); - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } - - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - scp->status |= UNKNOWN_MODE; /* graphics mode */ - scp->mode = cmd & 0xFF; - scp->xpixel = mp[0] * 8; - scp->ypixel = (mp[1] + rows_offset) * mp[2]; - scp->font_size = FONT_NONE; - /* move the mouse cursor at the center of the screen */ - scp->mouse_xpos = scp->xpixel / 2; - scp->mouse_ypos = scp->ypixel / 2; - splx(s); - - if (scp == cur_console) - set_mode(scp); - /* clear_graphics();*/ - - if (tp->t_winsize.ws_xpixel != scp->xpixel - || tp->t_winsize.ws_ypixel != scp->ypixel) { - tp->t_winsize.ws_xpixel = scp->xpixel; - tp->t_winsize.ws_ypixel = scp->ypixel; - pgsignal(tp->t_pgrp, SIGWINCH, 1); - } - return 0; - - case SW_VGA_MODEX: - if (crtc_type != KD_VGA) - return ENODEV; - mp = get_mode_param(scp, cmd & 0xff); - if (mp == NULL) - return ENODEV; - - s = spltty(); - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } - - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - scp->status |= UNKNOWN_MODE; /* graphics mode */ - scp->mode = cmd & 0xFF; - scp->xpixel = 320; - scp->ypixel = 240; - scp->font_size = FONT_NONE; - splx(s); - - if (scp == cur_console) - set_mode(scp); - /* clear_graphics();*/ - if (tp->t_winsize.ws_xpixel != scp->xpixel - || tp->t_winsize.ws_ypixel != scp->ypixel) { - tp->t_winsize.ws_xpixel = scp->xpixel; - tp->t_winsize.ws_ypixel = scp->ypixel; - pgsignal(tp->t_pgrp, SIGWINCH, 1); - } - return 0; - case VT_SETMODE: /* set screen switcher mode */ { struct vt_mode *mode; @@ -1906,7 +1563,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case VT_RELDISP: /* screen switcher ioctl */ - switch(*data) { + switch(*(int *)data) { case VT_FALSE: /* user refuses to release screen, abort */ if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { old_scp->status &= ~SWITCH_WAIT_REL; @@ -1946,32 +1603,32 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) for (i = 0; i < MAXCONS; i++) { tp = VIRTUAL_TTY(i); if (!(tp->t_state & TS_ISOPEN)) { - *data = i + 1; + *(int *)data = i + 1; return 0; } } return EINVAL; case VT_ACTIVATE: /* switch to screen *data */ - return switch_scr(scp, (*data) - 1); + return switch_scr(scp, *(int *)data - 1); case VT_WAITACTIVE: /* wait for switch to occur */ - if (*data > MAXCONS || *data < 0) + if (*(int *)data > MAXCONS || *(int *)data < 0) return EINVAL; - if (minor(dev) == (*data) - 1) + if (minor(dev) == *(int *)data - 1) return 0; - if (*data == 0) { + if (*(int *)data == 0) { if (scp == cur_console) return 0; } else - scp = console[(*data) - 1]; + scp = console[*(int *)data - 1]; while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; return error; case VT_GETACTIVE: - *data = get_scr_num()+1; + *(int *)data = get_scr_num()+1; return 0; case KDENABIO: /* allow io operations */ @@ -1991,102 +1648,28 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) #endif return 0; - case KDSETMODE: /* set current mode of this (virtual) console */ - switch (*data) { - case KD_TEXT: /* switch to TEXT (known) mode */ - /* restore fonts & palette ! */ - if (crtc_type == KD_VGA) { - if (!VESA_MODE(scp->mode)) { -#if 0 - /* - * FONT KLUDGE - * Don't load fonts for now... XXX - */ - if (fonts_loaded & FONT_8) - copy_font(LOAD, FONT_8, font_8); - if (fonts_loaded & FONT_14) - copy_font(LOAD, FONT_14, font_14); - if (fonts_loaded & FONT_16) - copy_font(LOAD, FONT_16, font_16); -#endif - } - load_palette(palette); - } - - /* move hardware cursor out of the way */ - outb(crtc_addr, 14); - outb(crtc_addr + 1, 0xff); - outb(crtc_addr, 15); - outb(crtc_addr + 1, 0xff); - - /* FALL THROUGH */ - - case KD_TEXT1: /* switch to TEXT (known) mode */ - s = spltty(); - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - scp->status |= UNKNOWN_MODE; - splx(s); - /* no restore fonts & palette */ - if (crtc_type == KD_VGA) - set_mode(scp); - scp->status &= ~UNKNOWN_MODE; - clear_screen(scp); - return 0; - - case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ - s = spltty(); - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - scp->status |= UNKNOWN_MODE; - splx(s); - return 0; - default: + case KDSKBSTATE: /* set keyboard state (locks) */ + if (*(int *)data & ~LOCK_KEY_MASK) return EINVAL; - } - /* NOT REACHED */ - - case KDGETMODE: /* get current mode of this (virtual) console */ - *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; - return 0; - - case KDSBORDER: /* set border color of this (virtual) console */ - scp->border = *data; + scp->status &= ~LOCK_KEY_MASK; + scp->status |= *(int *)data; if (scp == cur_console) - set_border(scp->border); + update_leds(scp->status); return 0; - case KDSKBSTATE: /* set keyboard state (locks) */ - if (*data >= 0 && *data <= LOCK_KEY_MASK) { - scp->status &= ~LOCK_KEY_MASK; - scp->status |= *data; - if (scp == cur_console) - update_leds(scp->status); - return 0; - } - return EINVAL; - case KDGKBSTATE: /* get keyboard state (locks) */ - *data = scp->status & LOCK_KEY_MASK; + *(int *)data = scp->status & LOCK_KEY_MASK; return 0; case KDSETRAD: /* set keyboard repeat & delay rates */ - if (*data & 0x80) + if (*(int *)data & ~0x7f) return EINVAL; if (sc_kbdc != NULL) - set_keyboard(KBDC_SET_TYPEMATIC, *data); + set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data); return 0; case KDSKBMODE: /* set keyboard mode */ - switch (*data) { + switch (*(int *)data) { case K_RAW: /* switch to RAW scancode mode */ scp->status &= ~KBD_CODE_MODE; scp->status |= KBD_RAW_MODE; @@ -2108,7 +1691,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) /* NOT REACHED */ case KDGKBMODE: /* get keyboard mode */ - *data = (scp->status & KBD_RAW_MODE) ? K_RAW : + *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); return 0; @@ -2147,21 +1730,20 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case KDGKBTYPE: /* get keyboard type */ - *data = 0; /* type not known (yet) */ + *(int *)data = 0; /* type not known (yet) */ return 0; case KDSETLED: /* set keyboard LED status */ - if (*data >= 0 && *data <= LED_MASK) { - scp->status &= ~LED_MASK; - scp->status |= *data; - if (scp == cur_console) - update_leds(scp->status); - return 0; - } - return EINVAL; + if (*(int *)data & ~LED_MASK) + return EINVAL; + scp->status &= ~LED_MASK; + scp->status |= *(int *)data; + if (scp == cur_console) + update_leds(scp->status); + return 0; case KDGETLED: /* get keyboard LED status */ - *data = scp->status & LED_MASK; + *(int *)data = scp->status & LED_MASK; return 0; case GETFKEY: /* get functionkey string */ @@ -2216,7 +1798,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case PIO_FONT8x8: /* set 8x8 dot font */ - if (crtc_type != KD_VGA) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; bcopy(data, font_8, 8*256); fonts_loaded |= FONT_8; @@ -2225,17 +1807,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * Always use the font page #0. XXX * Don't load if the current font size is not 8x8. */ - if (!VESA_MODE(cur_console->mode) - && !(cur_console->status & UNKNOWN_MODE) - && (cur_console->font_size < 14)) { - copy_font(LOAD, FONT_8, font_8); - if (flags & CHAR_CURSOR) - set_destructive_cursor(cur_console); - } + if (ISTEXTSC(cur_console) && (cur_console->font_size < 14)) + copy_font(cur_console, LOAD, 8, font_8); return 0; case GIO_FONT8x8: /* get 8x8 dot font */ - if (crtc_type != KD_VGA) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; if (fonts_loaded & FONT_8) { bcopy(font_8, data, 8*256); @@ -2245,7 +1822,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return ENXIO; case PIO_FONT8x14: /* set 8x14 dot font */ - if (crtc_type != KD_VGA) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; bcopy(data, font_14, 14*256); fonts_loaded |= FONT_14; @@ -2254,17 +1831,13 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * Always use the font page #0. XXX * Don't load if the current font size is not 8x14. */ - if (!VESA_MODE(cur_console->mode) - && !(cur_console->status & UNKNOWN_MODE) - && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) { - copy_font(LOAD, FONT_14, font_14); - if (flags & CHAR_CURSOR) - set_destructive_cursor(cur_console); - } + if (ISTEXTSC(cur_console) + && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) + copy_font(cur_console, LOAD, 14, font_14); return 0; case GIO_FONT8x14: /* get 8x14 dot font */ - if (crtc_type != KD_VGA) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; if (fonts_loaded & FONT_14) { bcopy(font_14, data, 14*256); @@ -2274,7 +1847,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return ENXIO; case PIO_FONT8x16: /* set 8x16 dot font */ - if (crtc_type != KD_VGA) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; bcopy(data, font_16, 16*256); fonts_loaded |= FONT_16; @@ -2283,17 +1856,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * Always use the font page #0. XXX * Don't load if the current font size is not 8x16. */ - if (!VESA_MODE(cur_console->mode) - && !(cur_console->status & UNKNOWN_MODE) - && (cur_console->font_size >= 16)) { - copy_font(LOAD, FONT_16, font_16); - if (flags & CHAR_CURSOR) - set_destructive_cursor(cur_console); - } + if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16)) + copy_font(cur_console, LOAD, 16, font_16); return 0; case GIO_FONT8x16: /* get 8x16 dot font */ - if (crtc_type != KD_VGA) + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) return ENXIO; if (fonts_loaded & FONT_16) { bcopy(font_16, data, 16*256); @@ -2320,7 +1888,7 @@ scstart(struct tty *tp) struct clist *rbp; int s, len; u_char buf[PCBURST]; - scr_stat *scp = get_scr_stat(tp->t_dev); + scr_stat *scp = sc_get_scr_stat(tp->t_dev); if (scp->status & SLKED || blink_in_progress) return; /* XXX who repeats the call when the above flags are cleared? */ @@ -2424,7 +1992,7 @@ sccnputc(dev_t dev, int c) scp->term = kernel_console; current_default = &kernel_default; - if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) + if (scp == cur_console && !ISGRAPHSC(scp)) remove_cursor_image(scp); buf[0] = c; ansi_put(scp, buf, 1); @@ -2479,25 +2047,28 @@ sccnupdate(scr_stat *scp) if (font_loading_in_progress) return; - if (panicstr) { + if (panicstr || shutdown_in_progress) { scsplash_stick(FALSE); run_scrn_saver = FALSE; + } else if (scp != cur_console) { + return; } + if (!run_scrn_saver) scrn_idle = FALSE; if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) - if (scrn_blanked > 0) + if (scp->status & SAVER_RUNNING) stop_scrn_saver(current_saver); if (scp != cur_console || blink_in_progress || switch_in_progress) return; - if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0) + if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) scrn_update(scp, TRUE); } -static scr_stat -*get_scr_stat(dev_t dev) +scr_stat +*sc_get_scr_stat(dev_t dev) { int unit = minor(dev); @@ -2556,6 +2127,8 @@ scrn_timer(void *arg) scintr(0); } + scp = cur_console; + /* should we stop the screen saver? */ getmicrouptime(&tv); if (panicstr || shutdown_in_progress) { @@ -2571,7 +2144,7 @@ scrn_timer(void *arg) run_scrn_saver = TRUE; } if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) - if (scrn_blanked > 0) + if (scp->status & SAVER_RUNNING) stop_scrn_saver(current_saver); /* should we just return ? */ @@ -2583,14 +2156,13 @@ scrn_timer(void *arg) } /* Update the screen */ - scp = cur_console; - if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0) + if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) scrn_update(scp, TRUE); /* should we activate the screen saver? */ if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) - if ((scp->status & UNKNOWN_MODE) == 0 || scrn_blanked > 0) - (*current_saver)(TRUE); + if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING)) + scrn_saver(current_saver, TRUE); if (arg) timeout(scrn_timer, (void *)TRUE, hz / 25); @@ -2678,9 +2250,9 @@ add_scrn_saver(void (*this_saver)(int)) if (current_saver != default_saver) return EBUSY; - current_saver = this_saver; + run_scrn_saver = FALSE; saver_mode = CONS_LKM_SAVER; - run_scrn_saver = (scrn_blank_time > 0); + current_saver = this_saver; return 0; } @@ -2708,9 +2280,21 @@ remove_scrn_saver(void (*this_saver)(int)) } static void +scrn_saver(void (*saver)(int), int blank) +{ + static int busy = FALSE; + + if (busy) + return; + busy = TRUE; + (*saver)(blank); + busy = FALSE; +} + +static void stop_scrn_saver(void (*saver)(int)) { - (*saver)(FALSE); + scrn_saver(saver, FALSE); run_scrn_saver = FALSE; /* the screen saver may have chosen not to stop after all... */ if (scrn_blanked > 0) @@ -2727,8 +2311,8 @@ wait_scrn_saver_stop(void) { int error = 0; - run_scrn_saver = FALSE; while (scrn_blanked > 0) { + run_scrn_saver = FALSE; error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); run_scrn_saver = FALSE; if (error != ERESTART) @@ -2737,8 +2321,8 @@ wait_scrn_saver_stop(void) return error; } -static void -clear_screen(scr_stat *scp) +void +sc_clear_screen(scr_stat *scp) { move_crsr(scp, 0, 0); scp->cursor_oldpos = scp->cursor_pos; @@ -2763,8 +2347,7 @@ switch_scr(scr_stat *scp, u_int next_scr) switch_in_progress = FALSE; if (next_scr >= MAXCONS || switch_in_progress || - (cur_console->smode.mode == VT_AUTO - && cur_console->status & UNKNOWN_MODE)) { + (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { do_bell(scp, BELL_PITCH, BELL_DURATION); return EINVAL; } @@ -2816,25 +2399,26 @@ exchange_scr(void) { move_crsr(old_scp, old_scp->xpos, old_scp->ypos); cur_console = new_scp; - if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ - if (crtc_type == KD_VGA) + if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) { + if (adp_flags & V_ADP_MODECHANGE) set_mode(new_scp); } move_crsr(new_scp, new_scp->xpos, new_scp->ypos); - if (!(new_scp->status & UNKNOWN_MODE) && (flags & CHAR_CURSOR)) + if (ISTEXTSC(new_scp) && (flags & CHAR_CURSOR)) set_destructive_cursor(new_scp); - if ((old_scp->status & UNKNOWN_MODE) && crtc_type == KD_VGA) - load_palette(palette); + if (ISGRAPHSC(old_scp)) + load_palette(new_scp, palette); if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) shfts = ctls = alts = agrs = metas = accents = 0; - set_border(new_scp->border); + set_border(new_scp, new_scp->border); update_leds(new_scp->status); delayed_next_scr = FALSE; mark_all(new_scp); - if (new_scp->mode == 0x102) { - memset_io(Crtat, 0, 800*600/8); - } + + /* FIXME: the screen size may be larger than a 64K segment. */ + if (ISPIXELSC(new_scp)) + memset_io(Crtat, 0, new_scp->xpixel*new_scp->ypixel/8); } static void @@ -2883,7 +2467,7 @@ scan_esc(scr_stat *scp, u_char c) return; #endif case 'c': /* Clear screen & home */ - clear_screen(scp); + sc_clear_screen(scp); break; case '(': /* iso-2022: designate 94 character set to G0 */ @@ -2969,7 +2553,7 @@ scan_esc(scr_stat *scp, u_char c) scp->cursor_pos, scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); mark_for_update(scp, scp->cursor_pos - scp->scr_buf); - mark_for_update(scp, scp->xsize * scp->ysize); + mark_for_update(scp, scp->xsize * scp->ysize - 1); remove_cutmarking(scp); break; case 1: /* clear from beginning of display to cursor */ @@ -3031,7 +2615,7 @@ scan_esc(scr_stat *scp, u_char c) fillw(scp->term.cur_color | scr_map[0x20], src, n * scp->xsize); mark_for_update(scp, scp->ypos * scp->xsize); - mark_for_update(scp, scp->xsize * scp->ysize); + mark_for_update(scp, scp->xsize * scp->ysize - 1); break; case 'M': /* Delete n lines */ @@ -3046,7 +2630,7 @@ scan_esc(scr_stat *scp, u_char c) fillw(scp->term.cur_color | scr_map[0x20], src, n * scp->xsize); mark_for_update(scp, scp->ypos * scp->xsize); - mark_for_update(scp, scp->xsize * scp->ysize); + mark_for_update(scp, scp->xsize * scp->ysize - 1); break; case 'P': /* Delete n chars */ @@ -3287,7 +2871,7 @@ scan_esc(scr_stat *scp, u_char c) if (scp->term.num_param == 1) { scp->border=scp->term.param[0] & 0xff; if (scp == cur_console) - set_border(scp->border); + set_border(cur_console, scp->border); } break; @@ -3304,8 +2888,8 @@ scan_esc(scr_stat *scp, u_char c) flags |= BLINK_CURSOR; else flags &= ~BLINK_CURSOR; - if ((scp->term.param[0] & 0x02) && - crtc_type == KD_VGA && !VESA_MODE(bios_video_mode)) + if ((scp->term.param[0] & 0x02) + && ISFONTAVAIL(get_adapter(scp)->va_flags)) flags |= CHAR_CURSOR; else flags &= ~CHAR_CURSOR; @@ -3318,9 +2902,9 @@ scan_esc(scr_stat *scp, u_char c) * The cursor shape is global property; all virtual consoles * are affected. Update the cursor in the current console... */ - if (!(cur_console->status & UNKNOWN_MODE)) { + if (!ISGRAPHSC(cur_console)) { remove_cursor_image(cur_console); - if (crtc_type == KD_VGA && (flags & CHAR_CURSOR)) + if (flags & CHAR_CURSOR) set_destructive_cursor(cur_console); draw_cursor_image(cur_console); } @@ -3461,7 +3045,7 @@ outloop: break; case 0x0c: /* form feed, clears screen */ - clear_screen(scp); + sc_clear_screen(scp); break; case 0x0d: /* return, return to pos 0 */ @@ -3508,42 +3092,17 @@ outloop: static void scinit(void) { - u_int hw_cursor; + int col; + int row; u_int i; if (init_done != COLD) return; init_done = WARM; - /* - * Ensure a zero start address. This is mainly to recover after - * switching from pcvt using userconfig(). The registers are w/o - * for old hardware so it's too hard to relocate the active screen - * memory. - */ - outb(crtc_addr, 12); - outb(crtc_addr + 1, 0); - outb(crtc_addr, 13); - outb(crtc_addr + 1, 0); - - /* extract cursor location */ - outb(crtc_addr, 14); - hw_cursor = inb(crtc_addr + 1) << 8; - outb(crtc_addr, 15); - hw_cursor |= inb(crtc_addr + 1); - - /* - * Validate cursor location. It may be off the screen. Then we must - * not use it for the initial buffer offset. - */ - if (hw_cursor >= ROW * COL) - hw_cursor = (ROW - 1) * COL; - - /* move hardware cursor out of the way */ - outb(crtc_addr, 14); - outb(crtc_addr + 1, 0xff); - outb(crtc_addr, 15); - outb(crtc_addr + 1, 0xff); + /* extract the hardware cursor location and move it out of the way */ + (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row); + (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1); /* set up the first console */ current_default = &user_default; @@ -3551,51 +3110,22 @@ scinit(void) init_scp(console[0]); cur_console = console[0]; - /* discard the video mode table if we are not familiar with it... */ - if (video_mode_ptr) { - bzero(mode_map, sizeof(mode_map)); - bcopy(video_mode_ptr + MODE_PARAM_SIZE*console[0]->mode, - vgaregs2, sizeof(vgaregs2)); - switch (comp_vgaregs(vgaregs, video_mode_ptr - + MODE_PARAM_SIZE*console[0]->mode)) { - case COMP_IDENTICAL: - map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); - /* - * This is a kludge for Toshiba DynaBook SS433 whose BIOS video - * mode table entry has the actual # of rows at the offset 1; - * BIOSes from other manufacturers store the # of rows - 1 there. - * XXX - */ - rows_offset = vgaregs[1] + 1 - - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; - break; - case COMP_SIMILAR: - map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); - mode_map[console[0]->mode] = vgaregs; - rows_offset = vgaregs[1] + 1 - - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; - vgaregs[1] -= rows_offset - 1; - break; - case COMP_DIFFERENT: - default: - video_mode_ptr = NULL; - mode_map[console[0]->mode] = vgaregs; - rows_offset = 1; - break; - } - } - /* copy screen to temporary buffer */ - if (!VESA_MODE(console[0]->mode)) + if (ISTEXTSC(console[0])) memcpy_fromio(sc_buffer, Crtat, console[0]->xsize * console[0]->ysize * sizeof(u_short)); console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos = sc_buffer; - console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; + if (col >= console[0]->xsize) + col = 0; + if (row >= console[0]->ysize) + row = console[0]->ysize - 1; + console[0]->xpos = col; + console[0]->ypos = row; + console[0]->cursor_pos = console[0]->cursor_oldpos = + sc_buffer + row*console[0]->xsize + col; console[0]->cursor_saveunder = *console[0]->cursor_pos; - console[0]->xpos = hw_cursor % COL; - console[0]->ypos = hw_cursor / COL; for (i=1; i<MAXCONS; i++) console[i] = NULL; kernel_console.esc = 0; @@ -3610,28 +3140,26 @@ scinit(void) scr_map[i] = scr_rmap[i] = i; } - /* Save font and palette if VGA */ - if (crtc_type == KD_VGA) { - if (!VESA_MODE(bios_video_mode)) { - if (fonts_loaded & FONT_16) { - copy_font(LOAD, FONT_16, font_16); - } else { - copy_font(SAVE, FONT_16, font_16); - fonts_loaded = FONT_16; - } - set_destructive_cursor(console[0]); + /* Save font and palette */ + if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) { + if (fonts_loaded & FONT_16) { + copy_font(cur_console, LOAD, 16, font_16); + } else { + copy_font(cur_console, SAVE, 16, font_16); + fonts_loaded = FONT_16; + set_destructive_cursor(cur_console); } - save_palette(); + /* + * FONT KLUDGE + * Always use the font page #0. XXX + */ + (*biosvidsw.show_font)(cur_console->adp, 0); } + save_palette(cur_console, palette); #ifdef SC_SPLASH_SCREEN - /* - * If not booting verbosely, put up the splash. - * Note that the splash screen is not currently supported in - * the VESA mode. - */ - if (!(boothowto & RB_VERBOSE) && !VESA_MODE(bios_video_mode)) - scsplash_init(); + /* put up the splash. */ + scsplash_init(cur_console); #endif } @@ -3646,52 +3174,79 @@ scshutdown(int howto, void *arg) shutdown_in_progress = TRUE; } -static void -map_mode_table(char *map[], char *table, int max) +int +sc_clean_up(scr_stat *scp) { - int i; + int error; - for(i = 0; i < max; ++i) - map[i] = table + i*MODE_PARAM_SIZE; - for(; i < MODE_MAP_SIZE; ++i) - map[i] = NULL; + if ((error = wait_scrn_saver_stop())) + return error; + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + return 0; } -static int -map_mode_num(int mode) +void +sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) { - static struct { - int from; - int to; - } mode_map[] = { - { M_ENH_B80x43, M_ENH_B80x25 }, - { M_ENH_C80x43, M_ENH_C80x25 }, - { M_VGA_M80x30, M_VGA_M80x25 }, - { M_VGA_C80x30, M_VGA_C80x25 }, - { M_VGA_M80x50, M_VGA_M80x25 }, - { M_VGA_C80x50, M_VGA_C80x25 }, - { M_VGA_M80x60, M_VGA_M80x25 }, - { M_VGA_C80x60, M_VGA_C80x25 }, - { M_VGA_MODEX, M_VGA_CG320 }, - }; - int i; + if (scp->scr_buf) + free(scp->scr_buf, M_DEVBUF); + scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), + M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); - for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { - if (mode_map[i].from == mode) - return mode_map[i].to; + if (clear) { + /* clear the screen and move the text cursor to the top-left position */ + sc_clear_screen(scp); + } else { + /* retain the current cursor position, but adjust pointers */ + move_crsr(scp, scp->xpos, scp->ypos); + scp->cursor_oldpos = scp->cursor_pos; } - return mode; + + /* move the mouse cursor at the center of the screen */ + sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); } -static char -*get_mode_param(scr_stat *scp, int mode) +void +sc_alloc_cut_buffer(scr_stat *scp, int wait) { - if (mode >= MODE_MAP_SIZE) - mode = map_mode_num(mode); - if (mode < MODE_MAP_SIZE) - return mode_map[mode]; - else - return NULL; + if ((cut_buffer == NULL) + || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { + if (cut_buffer != NULL) + free(cut_buffer, M_DEVBUF); + cut_buffer_size = scp->xsize * scp->ysize + 1; + cut_buffer = (u_char *)malloc(cut_buffer_size, + M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); + if (cut_buffer != NULL) + cut_buffer[0] = '\0'; + } +} + +void +sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) +{ + u_short *usp; + + if (lines < scp->ysize) + lines = scp->ysize; + + usp = scp->history; + scp->history = NULL; + if (usp != NULL) { + free(usp, M_DEVBUF); + if (extra > 0) + extra_history_size += extra; + } + + scp->history_size = lines * scp->xsize; + if (lines > imax(sc_history_size, scp->ysize)) + extra_history_size -= lines - imax(sc_history_size, scp->ysize); + usp = (u_short *)malloc(scp->history_size * sizeof(u_short), + M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); + if (usp != NULL) + bzero(usp, scp->history_size * sizeof(u_short)); + scp->history_head = scp->history_pos = usp; + scp->history = usp; } static scr_stat @@ -3701,22 +3256,15 @@ static scr_stat scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); init_scp(scp); - scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos = - (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), - M_DEVBUF, M_WAITOK); - scp->mouse_pos = scp->mouse_oldpos = - scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + - scp->mouse_xpos/8); - scp->history_head = scp->history_pos = - (u_short *)malloc(scp->history_size*sizeof(u_short), - M_DEVBUF, M_WAITOK); - bzero(scp->history_head, scp->history_size*sizeof(u_short)); - scp->history = scp->history_head; + sc_alloc_scr_buffer(scp, TRUE, TRUE); + if (ISMOUSEAVAIL(get_adapter(scp)->va_flags)) + sc_alloc_cut_buffer(scp, TRUE); + sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); /* SOS - if (crtc_type == KD_VGA && video_mode_ptr) + if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE) set_mode(scp); */ - clear_screen(scp); + sc_clear_screen(scp); scp->cursor_saveunder = *scp->cursor_pos; return scp; } @@ -3724,43 +3272,29 @@ static scr_stat static void init_scp(scr_stat *scp) { - switch(crtc_type) { - case KD_VGA: - if (VESA_MODE(bios_video_mode)) - scp->mode = bios_video_mode; - else if (crtc_addr == MONO_BASE) - scp->mode = M_VGA_M80x25; - else - scp->mode = M_VGA_C80x25; - scp->font_size = 16; - break; - case KD_CGA: - if (crtc_addr == MONO_BASE) - scp->mode = M_B80x25; - else - scp->mode = M_C80x25; - scp->font_size = 8; - break; - case KD_EGA: - if (crtc_addr == MONO_BASE) - scp->mode = M_B80x25; - else - scp->mode = M_C80x25; - scp->font_size = 14; - break; - case KD_MONO: - case KD_HERCULES: - default: - scp->mode = M_EGAMONO80x25; - scp->font_size = 14; - break; + video_info_t info; + + scp->adp = V_ADP_PRIMARY; + (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info); + + scp->status = 0; + scp->mode = scp->initial_mode = initial_video_mode; + scp->scr_buf = NULL; + if (info.vi_flags & V_INFO_GRAPHICS) { + scp->status |= GRAPHICS_MODE; + scp->xpixel = info.vi_width; + scp->ypixel = info.vi_height; + scp->xsize = info.vi_width/8; + scp->ysize = info.vi_height/info.vi_cheight; + scp->font_size = FONT_NONE; + } else { + scp->xsize = info.vi_width; + scp->ysize = info.vi_height; + scp->xpixel = scp->xsize*8; + scp->ypixel = scp->ysize*info.vi_cheight; + scp->font_size = info.vi_cheight; } - scp->initial_mode = scp->mode; - - scp->xsize = COL; - scp->ysize = ROW; - scp->xpixel = scp->xsize * 8; - scp->ypixel = scp->ysize * scp->font_size; + scp->xoff = scp->yoff = 0; scp->xpos = scp->ypos = 0; scp->saved_xpos = scp->saved_ypos = -1; scp->start = scp->xsize * scp->ysize; @@ -3788,7 +3322,7 @@ init_scp(scr_stat *scp) scp->proc = NULL; scp->smode.mode = VT_AUTO; scp->history_head = scp->history_pos = scp->history = NULL; - scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; + scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; } static u_char @@ -4237,9 +3771,9 @@ next_code: scsplash_stick(FALSE); stop_scrn_saver(current_saver); } else { - if ((cur_console->status & UNKNOWN_MODE) == 0) { + if (!ISGRAPHSC(cur_console)) { scsplash_stick(TRUE); - (*current_saver)(TRUE); + scrn_saver(current_saver, TRUE); } } } @@ -4506,459 +4040,100 @@ update_leds(int which) set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); } -void +int set_mode(scr_stat *scp) { - char special_modetable[MODE_PARAM_SIZE]; - char *mp; - int s; - int i; + video_info_t info; + video_adapter_t *adp; - if (scp != cur_console) - return; + /* reject unsupported mode */ + if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) + return 1; - /* - * even if mode switching is disabled, we can change back - * to the initial mode or the custom mode based on the initial - * mode if we have saved register values upon start-up. - */ - mp = get_mode_param(scp, scp->mode); - if (mp == NULL) - return; - bcopy(mp, &special_modetable, sizeof(special_modetable)); + /* if this vty is not currently showing, do nothing */ + if (scp != cur_console) + return 0; /* setup video hardware for the given mode */ - switch (scp->mode) { - case M_VGA_C80x60: case M_VGA_M80x60: - special_modetable[2] = 0x08; - special_modetable[19] = 0x47; - goto special_480l; - - case M_VGA_C80x30: case M_VGA_M80x30: - special_modetable[19] = 0x4f; -special_480l: - special_modetable[9] |= 0xc0; - special_modetable[16] = 0x08; - special_modetable[17] = 0x3e; - special_modetable[26] = 0xea; - special_modetable[28] = 0xdf; - special_modetable[31] = 0xe7; - special_modetable[32] = 0x04; - goto setup_mode; - - case M_ENH_C80x43: case M_ENH_B80x43: - special_modetable[28] = 87; - goto special_80x50; - - case M_VGA_C80x50: case M_VGA_M80x50: -special_80x50: - special_modetable[2] = 8; - special_modetable[19] = 7; - goto setup_mode; - - case M_VGA_C40x25: case M_VGA_C80x25: - case M_VGA_M80x25: - case M_B40x25: case M_C40x25: - case M_B80x25: case M_C80x25: - case M_ENH_B40x25: case M_ENH_C40x25: - case M_ENH_B80x25: case M_ENH_C80x25: - case M_EGAMONO80x25: - -setup_mode: - set_vgaregs(special_modetable); - scp->font_size = special_modetable[2]; - - /* set font type (size) */ - if (scp->font_size < 14) { - if (fonts_loaded & FONT_8) - copy_font(LOAD, FONT_8, font_8); - i = 0x0a; /* font 2 */ - } else if (scp->font_size >= 16) { - if (fonts_loaded & FONT_16) - copy_font(LOAD, FONT_16, font_16); - i = 0x00; /* font 0 */ - } else { - if (fonts_loaded & FONT_14) - copy_font(LOAD, FONT_14, font_14); - i = 0x05; /* font 1 */ + adp = get_adapter(scp); + (*biosvidsw.set_mode)(scp->adp, scp->mode); + Crtat = adp->va_window; + + if (!(scp->status & GRAPHICS_MODE)) { + /* load appropriate font */ + if (!(scp->status & PIXEL_MODE) + && ISFONTAVAIL(get_adapter(scp)->va_flags)) { + if (scp->font_size < 14) { + if (fonts_loaded & FONT_8) + copy_font(scp, LOAD, 8, font_8); + } else if (scp->font_size >= 16) { + if (fonts_loaded & FONT_16) + copy_font(scp, LOAD, 16, font_16); + } else { + if (fonts_loaded & FONT_14) + copy_font(scp, LOAD, 14, font_14); + } + /* + * FONT KLUDGE: + * This is an interim kludge to display correct font. + * Always use the font page #0 on the video plane 2. + * Somehow we cannot show the font in other font pages on + * some video cards... XXX + */ + (*biosvidsw.show_font)(scp->adp, 0); } - /* - * FONT KLUDGE: - * This is an interim kludge to display correct font. - * Always use the font page #0 on the video plane 2. - * Somehow we cannot show the font in other font pages on - * some video cards... XXX - */ - i = 0x00; - s = splhigh(); - outb(TSIDX, 0x00); outb(TSREG, 0x01); - outb(TSIDX, 0x03); outb(TSREG, i); - outb(TSIDX, 0x00); outb(TSREG, 0x03); - splx(s); - if (flags & CHAR_CURSOR) - set_destructive_cursor(scp); mark_all(scp); - break; - - case M_VGA_MODEX: - /* "unchain" the VGA mode */ - special_modetable[5-1+0x04] &= 0xf7; - special_modetable[5-1+0x04] |= 0x04; - /* turn off doubleword mode */ - special_modetable[10+0x14] &= 0xbf; - /* turn off word adressing */ - special_modetable[10+0x17] |= 0x40; - /* set logical screen width */ - special_modetable[10+0x13] = 80; - /* set 240 lines */ - special_modetable[10+0x11] = 0x2c; - special_modetable[10+0x06] = 0x0d; - special_modetable[10+0x07] = 0x3e; - special_modetable[10+0x10] = 0xea; - special_modetable[10+0x11] = 0xac; - special_modetable[10+0x12] = 0xdf; - special_modetable[10+0x15] = 0xe7; - special_modetable[10+0x16] = 0x06; - /* set vertical sync polarity to reflect aspect ratio */ - special_modetable[9] = 0xe3; - goto setup_grmode; - - case M_BG320: case M_CG320: case M_BG640: - case M_CG320_D: case M_CG640_E: - case M_CG640x350: case M_ENH_CG640: - case M_BG640x480: case M_CG640x480: case M_VGA_CG320: - -setup_grmode: - set_vgaregs(special_modetable); - scp->font_size = FONT_NONE; - break; - - default: - /* call user defined function XXX */ - break; - } - - /* set border color for this (virtual) console */ - set_border(scp->border); - return; -} - -void -set_border(u_char color) -{ - switch (crtc_type) { - case KD_EGA: - case KD_VGA: - inb(crtc_addr + 6); /* reset flip-flop */ - outb(ATC, 0x31); outb(ATC, color); - break; - case KD_CGA: - outb(crtc_addr + 5, color & 0x0f); /* color select register */ - break; - case KD_MONO: - case KD_HERCULES: - default: - break; - } -} - -static void -set_vgaregs(char *modetable) -{ - int i, s = splhigh(); - - outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ - for (i=0; i<4; i++) { /* program sequencer */ - outb(TSIDX, i+1); - outb(TSREG, modetable[i+5]); - } - outb(MISC, modetable[9]); /* set dot-clock */ - outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ - outb(crtc_addr, 0x11); - outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); - for (i=0; i<25; i++) { /* program crtc */ - outb(crtc_addr, i); - if (i == 14 || i == 15) /* no hardware cursor */ - outb(crtc_addr+1, 0xff); - else - outb(crtc_addr+1, modetable[i+10]); - } - inb(crtc_addr+6); /* reset flip-flop */ - for (i=0; i<20; i++) { /* program attribute ctrl */ - outb(ATC, i); - outb(ATC, modetable[i+35]); - } - for (i=0; i<9; i++) { /* program graph data ctrl */ - outb(GDCIDX, i); - outb(GDCREG, modetable[i+55]); - } - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, 0x20); /* enable palette */ - splx(s); -} - -static void -read_vgaregs(char *buf) -{ - int i, j; - int s; - - bzero(buf, MODE_PARAM_SIZE); - - s = splhigh(); - - outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ - for (i=0, j=5; i<4; i++) { - outb(TSIDX, i+1); - buf[j++] = inb(TSREG); - } - buf[9] = inb(MISC + 10); /* dot-clock */ - outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ - - for (i=0, j=10; i<25; i++) { /* crtc */ - outb(crtc_addr, i); - buf[j++] = inb(crtc_addr+1); - } - for (i=0, j=35; i<20; i++) { /* attribute ctrl */ - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, i); - buf[j++] = inb(ATC + 1); } - for (i=0, j=55; i<9; i++) { /* graph data ctrl */ - outb(GDCIDX, i); - buf[j++] = inb(GDCREG); - } - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, 0x20); /* enable palette */ - - buf[0] = readb(0x44a); /* COLS */ - buf[1] = readb(0x484); /* ROWS */ - buf[2] = readb(0x485); /* POINTS */ - buf[3] = readb(0x44c); - buf[4] = readb(0x44d); + set_border(scp, scp->border); - splx(s); -} - -static int -comp_vgaregs(u_char *buf1, u_char *buf2) -{ - static struct { - u_char mask; - } params[MODE_PARAM_SIZE] = { - 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */ - 0xff, 0xff, /* page length */ - 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */ - 0xf3, /* misc register */ - 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */ - 0xff, 0xff, 0xff, 0x7f, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0x7f, 0xff, 0xff, - 0x7f, 0xff, 0xff, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */ - 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */ - 0xff, 0xff, 0xff, 0xff, - }; - int identical = TRUE; - int i; - - for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { - if (params[i].mask == 0) /* don't care */ - continue; - if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) - return COMP_DIFFERENT; - if (buf1[i] != buf2[i]) - identical = FALSE; - } - return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; - -#if 0 - for(i = 0; i < 20; ++i) { - if (*buf1++ != *buf2++) - return COMP_DIFFERENT; - } - buf1 += 2; /* skip the cursor shape */ - buf2 += 2; - for(i = 22; i < 24; ++i) { - if (*buf1++ != *buf2++) - return COMP_DIFFERENT; - } - buf1 += 2; /* skip the cursor position */ - buf2 += 2; - for(i = 26; i < MODE_PARAM_SIZE; ++i) { - if (*buf1++ != *buf2++) - return COMP_DIFFERENT; - } - return COMP_IDENTICAL; -#endif -} - -static void -dump_vgaregs(u_char *buf) -{ - int i; + /* move hardware cursor out of the way */ + (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); - for(i = 0; i < MODE_PARAM_SIZE;) { - printf("%02x ", buf[i]); - if ((++i % 16) == 0) - printf("\n"); - } + return 0; } -static void -set_font_mode(u_char *buf) +void +copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) { - int s = splhigh(); - + /* + * FONT KLUDGE: + * This is an interim kludge to display correct font. + * Always use the font page #0 on the video plane 2. + * Somehow we cannot show the font in other font pages on + * some video cards... XXX + */ font_loading_in_progress = TRUE; - - /* save register values */ - outb(TSIDX, 0x02); buf[0] = inb(TSREG); - outb(TSIDX, 0x04); buf[1] = inb(TSREG); - outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); - outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); - outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); - inb(crtc_addr + 6); - outb(ATC, 0x10); buf[5] = inb(ATC + 1); - - /* setup vga for loading fonts */ - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01); - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, 0x20); /* enable palette */ - -#if SLOW_VGA - outb(TSIDX, 0x00); outb(TSREG, 0x01); - outb(TSIDX, 0x02); outb(TSREG, 0x04); - outb(TSIDX, 0x04); outb(TSREG, 0x07); - outb(TSIDX, 0x00); outb(TSREG, 0x03); - outb(GDCIDX, 0x04); outb(GDCREG, 0x02); - outb(GDCIDX, 0x05); outb(GDCREG, 0x00); - outb(GDCIDX, 0x06); outb(GDCREG, 0x04); -#else - outw(TSIDX, 0x0100); - outw(TSIDX, 0x0402); - outw(TSIDX, 0x0704); - outw(TSIDX, 0x0300); - outw(GDCIDX, 0x0204); - outw(GDCIDX, 0x0005); - outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ -#endif - splx(s); -} - -static void -set_normal_mode(u_char *buf) -{ - char *modetable; - int s = splhigh(); - - /* setup vga for normal operation mode again */ - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, 0x10); outb(ATC, buf[5]); - inb(crtc_addr+6); /* reset flip-flop */ - outb(ATC, 0x20); /* enable palette */ - -#if SLOW_VGA - outb(TSIDX, 0x00); outb(TSREG, 0x01); - outb(TSIDX, 0x02); outb(TSREG, buf[0]); - outb(TSIDX, 0x04); outb(TSREG, buf[1]); - outb(TSIDX, 0x00); outb(TSREG, 0x03); - outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); - outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); - if (crtc_addr == MONO_BASE) { - outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); - } else { - outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); + if (operation == LOAD) { + (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256); + if (flags & CHAR_CURSOR) + set_destructive_cursor(scp); + } else if (operation == SAVE) { + (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256); } -#else - outw(TSIDX, 0x0100); - outw(TSIDX, 0x0002 | (buf[0] << 8)); - outw(TSIDX, 0x0004 | (buf[1] << 8)); - outw(TSIDX, 0x0300); - outw(GDCIDX, 0x0004 | (buf[2] << 8)); - outw(GDCIDX, 0x0005 | (buf[3] << 8)); - if (crtc_addr == MONO_BASE) - outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); - else - outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); -#endif - font_loading_in_progress = FALSE; - splx(s); -} - -void -copy_font(int operation, int font_type, char* font_image) -{ - int ch, line, segment, fontsize; - u_char buf[PARAM_BUFSIZE]; - u_char val; - - switch (font_type) { - default: - case FONT_8: - segment = 0x8000; - fontsize = 8; - break; - case FONT_14: - segment = 0x4000; - fontsize = 14; - break; - case FONT_16: - segment = 0x0000; - fontsize = 16; - break; - } - /* - * FONT KLUDGE - * Always use the font page #0. XXX - */ - segment = 0x0000; - outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ - outb(TSIDX, 0x01); outb(TSREG, val | 0x20); - set_font_mode(buf); - for (ch=0; ch < 256; ch++) - for (line=0; line < fontsize; line++) - if (operation) - writeb(VIDEOMEM+(segment)+(ch*32)+line, - font_image[(ch*fontsize)+line]); - else - font_image[(ch*fontsize)+line] = - readb(VIDEOMEM+(segment)+(ch*32)+line); - set_normal_mode(buf); - outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ } static void set_destructive_cursor(scr_stat *scp) { - u_char buf[PARAM_BUFSIZE]; u_char cursor[32]; - u_int32_t address; + u_char *font_buffer; + int font_size; int i; - char *font_buffer; + + if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp)) + return; if (scp->font_size < 14) { font_buffer = font_8; - address = VIDEOMEM + 0x8000; - } - else if (scp->font_size >= 16) { + font_size = 8; + } else if (scp->font_size >= 16) { font_buffer = font_16; - address = VIDEOMEM; - } - else { + font_size = 16; + } else { font_buffer = font_14; - address = VIDEOMEM + 0x4000; + font_size = 14; } - /* - * FONT KLUDGE - * Always use the font page #0. XXX - */ - address = VIDEOMEM; if (scp->status & MOUSE_VISIBLE) { if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) @@ -4983,9 +4158,18 @@ set_destructive_cursor(scr_stat *scp) #if 1 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; #endif - set_font_mode(buf); - memcpy_toio(address + DEAD_CHAR * 32, cursor, 32); - set_normal_mode(buf); + font_loading_in_progress = TRUE; + (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); + font_loading_in_progress = FALSE; +} + +void +sc_move_mouse(scr_stat *scp, int x, int y) +{ + scp->mouse_xpos = x; + scp->mouse_ypos = y; + scp->mouse_pos = scp->mouse_oldpos = + scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8; } static void @@ -4997,7 +4181,7 @@ set_mouse_pos(scr_stat *scp) scp->mouse_xpos = 0; if (scp->mouse_ypos < 0) scp->mouse_ypos = 0; - if (scp->status & UNKNOWN_MODE) { + if (!ISTEXTSC(scp)) { if (scp->mouse_xpos > scp->xpixel-1) scp->mouse_xpos = scp->xpixel-1; if (scp->mouse_ypos > scp->ypixel-1) @@ -5068,7 +4252,7 @@ mouse_cut(scr_stat *scp) j = i; /* trim trailing blank when crossing lines */ if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { - cut_buffer[j++] = '\n'; + cut_buffer[j++] = '\r'; i = j; } } @@ -5087,7 +4271,7 @@ mouse_cut(scr_stat *scp) scp->mouse_cut_start = p; else scp->mouse_cut_end = p; - cut_buffer[j++] = '\n'; + cut_buffer[j++] = '\r'; cut_buffer[j] = '\0'; } @@ -5112,7 +4296,7 @@ mouse_cut_start(scr_stat *scp) ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; scp->mouse_cut_end = scp->scr_buf + ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; - cut_buffer[0] = '\n'; + cut_buffer[0] = '\r'; cut_buffer[1] = '\0'; scp->status |= MOUSE_CUTTING; } else { @@ -5195,7 +4379,7 @@ mouse_cut_line(scr_stat *scp) scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) cut_buffer[i++] = *p & 0xff; - cut_buffer[i++] = '\n'; + cut_buffer[i++] = '\r'; cut_buffer[i] = '\0'; scp->status |= MOUSE_CUTTING; } @@ -5227,35 +4411,26 @@ mouse_paste(scr_stat *scp) static void draw_mouse_image(scr_stat *scp) { - u_int32_t address; - int i; - char *font_buffer; - u_char buf[PARAM_BUFSIZE]; u_short buffer[32]; u_short xoffset, yoffset; u_int32_t crt_pos = Crtat + 2*(scp->mouse_pos - scp->scr_buf); - int font_size = scp->font_size; + u_char *font_buffer; + int font_size; + int i; - if (font_size < 14) { + if (scp->font_size < 14) { font_buffer = font_8; - address = VIDEOMEM + 0x8000; - } - else if (font_size >= 16) { + font_size = 8; + } else if (scp->font_size >= 16) { font_buffer = font_16; - address = VIDEOMEM; - } - else { + font_size = 16; + } else { font_buffer = font_14; - address = VIDEOMEM + 0x4000; + font_size = 14; } - /* - * FONT KLUDGE - * Always use the font page #0. XXX - */ - address = VIDEOMEM; xoffset = scp->mouse_xpos % 8; - yoffset = scp->mouse_ypos % font_size; + yoffset = scp->mouse_ypos % scp->font_size; /* prepare mousepointer char's bitmaps */ bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), @@ -5290,9 +4465,11 @@ draw_mouse_image(scr_stat *scp) /* wait for vertical retrace to avoid jitter on some videocards */ while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; #endif - set_font_mode(buf); - memcpy_toio(address + SC_MOUSE_CHAR * 32, scp->mouse_cursor, 128); - set_normal_mode(buf); + font_loading_in_progress = TRUE; + (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, + SC_MOUSE_CHAR, 4); + font_loading_in_progress = FALSE; + writew(crt_pos, (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR); writew(crt_pos+2*scp->xsize, (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2)); @@ -5310,6 +4487,8 @@ remove_mouse_image(scr_stat *scp) { u_int32_t crt_pos = Crtat + 2*(scp->mouse_oldpos - scp->scr_buf); + if (!ISTEXTSC(scp)) + return; writew(crt_pos, *(scp->mouse_oldpos)); writew(crt_pos+2, *(scp->mouse_oldpos+1)); writew(crt_pos+2*scp->xsize, *(scp->mouse_oldpos+scp->xsize)); @@ -5360,30 +4539,6 @@ remove_cutmarking(scr_stat *scp) } static void -save_palette(void) -{ - int i; - - outb(PALRADR, 0x00); - for (i=0x00; i<0x300; i++) - palette[i] = inb(PALDATA); - inb(crtc_addr+6); /* reset flip/flop */ -} - -void -load_palette(char *palette) -{ - int i; - - outb(PIXMASK, 0xFF); /* no pixelmask */ - outb(PALWADR, 0x00); - for (i=0x00; i<0x300; i++) - outb(PALDATA, palette[i]); - inb(crtc_addr+6); /* reset flip/flop */ - outb(ATC, 0x20); /* enable palette */ -} - -static void do_bell(scr_stat *scp, int pitch, int duration) { if (cold || shutdown_in_progress) @@ -5411,7 +4566,7 @@ blink_screen(void *arg) { scr_stat *scp = arg; - if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) { + if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { blink_in_progress = FALSE; mark_all(scp); if (delayed_next_scr) @@ -5432,25 +4587,41 @@ blink_screen(void *arg) void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) { - if (!VESA_MODE(scp->mode)) { - memcpy_toio(Crtat+2*from, p+from, (to-from+1)*sizeof (u_short)); - } else if (scp->mode == 0x102) { - u_int32_t d, e; - int i,j; + u_char *font; + u_int32_t d, e; + u_char *f; + int font_size; + int line_length; + int xsize; + int i, j; + if (ISTEXTSC(scp)) { + memcpy_toio(Crtat+2*from, p+from, (to-from+1)*sizeof (u_short)); + } else /* if ISPIXELSC(scp) */ { if (mark) - mark = 255; - d = Crtat; - d += 10 + 6*16*100 + (from%80) + 16*100*(from/80); + mark = 255; + font_size = scp->font_size; + if (font_size < 14) + font = font_8; + else if (font_size >= 16) + font = font_16; + else + font = font_14; + line_length = scp->xpixel/8; + xsize = scp->xsize; + d = Crtat + + scp->xoff + scp->yoff*font_size*line_length + + (from%xsize) + font_size*line_length*(from/xsize); for (i = from ; i <= to ; i++) { e = d; - for (j = 0 ; j < 16; j++) { - writeb(e, mark^font_16[(p[i]&0xff)*16+j]); - e+=100; + f = &font[(p[i] & 0x00ff)*font_size]; + for (j = 0 ; j < font_size; j++, f++) { + writeb(e, mark^*f); + e += line_length; } d++; - if ((i % 80) == 79) - d += 20 + 15*100; + if ((i % xsize) == xsize - 1) + d += scp->xoff*2 + (font_size - 1)*line_length; } } } @@ -5458,40 +4629,42 @@ sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) #ifdef SC_SPLASH_SCREEN static void -scsplash_init(void) +scsplash_init(scr_stat *scp) { + video_info_t info; + /* * We currently assume the splash screen always use * VGA_CG320 mode and abort installation if this mode is not * supported with this video card. XXX */ - if (crtc_type != KD_VGA || get_mode_param(cur_console, M_VGA_CG320) == NULL) + if ((*biosvidsw.get_info)(scp->adp, M_VGA_CG320, &info)) return; - if (splash_load() == 0 && add_scrn_saver(scsplash) == 0) { - default_saver = scsplash; + if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) { + default_saver = scsplash_saver; scrn_blank_time = DEFAULT_BLANKTIME; run_scrn_saver = TRUE; - if (!(boothowto & RB_CONFIG)) { + if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) { scsplash_stick(TRUE); - scsplash(TRUE); + scsplash_saver(TRUE); } } } static void -scsplash(int show) +scsplash_saver(int show) { if (show) - splash(TRUE); + scsplash(TRUE); else if (!sticky_splash) - splash(FALSE); + scsplash(FALSE); } #endif /* SC_SPLASH_SCREEN */ CDEV_DRIVER_MODULE(sc, isa, sc_driver, sc_devclass, - CDEV_MAJOR, scdevsw, 0, 0); + CDEV_MAJOR, sc_cdevsw, 0, 0); #endif /* NSC */ diff --git a/sys/isa/syscons.h b/sys/isa/syscons.h index dc57f07..e8f9461 100644 --- a/sys/isa/syscons.h +++ b/sys/isa/syscons.h @@ -1,18 +1,18 @@ /*- - * Copyright (c) 1995-1997 Søren Schmidt + * Copyright (c) 1995-1998 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission + * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -25,8 +25,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ - * from: i386/isa syscons.h,v 1.39 + * $Id: syscons.h,v 1.40 1998/08/06 09:15:53 dfr Exp $ + * from: i386/isa syscons.h,v 1.40 */ #ifndef _I386_ISA_SYSCONS_H_ @@ -77,6 +77,9 @@ #define MOUSE_MOVED 0x01000 #define MOUSE_CUTTING 0x02000 #define MOUSE_VISIBLE 0x04000 +#define GRAPHICS_MODE 0x08000 +#define PIXEL_MODE 0x10000 +#define SAVER_RUNNING 0x20000 /* configuration flags */ #define VISUAL_BELL 0x00001 @@ -86,6 +89,7 @@ #define XT_KEYBD 0x00010 #define KBD_NORESET 0x00020 #define QUIET_BELL 0x00040 +#define VESA800X600 0x00080 /* attribute flags */ #define NORMAL_ATTR 0x00 @@ -96,9 +100,6 @@ #define FOREGROUND_CHANGED 0x10 #define BACKGROUND_CHANGED 0x20 -/* video hardware memory addresses */ -#define VIDEOMEM 0x000A0000 - /* misc defines */ #define FALSE 0 #define TRUE 1 @@ -116,20 +117,6 @@ #define FONT_14 4 #define FONT_16 8 -/* defines related to hardware addresses */ -#define MONO_BASE 0x3B4 /* crt controller base mono */ -#define COLOR_BASE 0x3D4 /* crt controller base color */ -#define MISC 0x3C2 /* misc output register */ -#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 */ - /* special characters */ #define cntlc 0x03 #define cntld 0x04 @@ -153,6 +140,7 @@ typedef struct term_stat { } term_stat; typedef struct scr_stat { + int adp; /* video adapter index */ u_short *scr_buf; /* buffer when off screen */ int xpos; /* current X position */ int ypos; /* current Y position */ @@ -162,6 +150,8 @@ typedef struct scr_stat { int ysize; /* Y text size */ int xpixel; /* X graphics size */ int ypixel; /* Y graphics size */ + int xoff; /* X offset in pixel mode */ + int yoff; /* Y offset in pixel mode */ int font_size; /* fontsize in Y direction */ int start; /* modified area start */ int end; /* modified area end */ @@ -200,7 +190,8 @@ typedef struct scr_stat { struct apmhook r_hook; /* reconfiguration support */ #endif #ifdef SC_SPLASH_SCREEN - u_char splash_save_mode; /* saved mode for splash screen */ + int splash_save_mode; /* saved mode for splash screen */ + int splash_save_status; /* saved status for splash screen */ #endif } scr_stat; @@ -209,18 +200,59 @@ typedef struct default_attr { int rev_color; /* reverse hardware color */ } default_attr; + +#define ISTEXTSC(scp) (!((scp)->status \ + & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE))) +#define ISGRAPHSC(scp) (((scp)->status \ + & (UNKNOWN_MODE | GRAPHICS_MODE))) +#define ISPIXELSC(scp) (((scp)->status \ + & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE))\ + == PIXEL_MODE) +#define ISUNKNOWNSC(scp) ((scp)->status & UNKNOWN_MODE) + +#define ISFONTAVAIL(af) ((af) & V_ADP_FONT) +#define ISMOUSEAVAIL(af) ((af) & V_ADP_FONT) +#define ISPALAVAIL(af) ((af) & V_ADP_PALETTE) + /* misc prototypes used by different syscons related LKM's */ -void set_border(u_char color); -void set_mode(scr_stat *scp); -void copy_font(int operation, int font_type, char* font_image); -void load_palette(char *palette); + +/* syscons.c */ +extern int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, int flag, + struct proc *p); + +int set_mode(scr_stat *scp); +scr_stat *sc_get_scr_stat(dev_t dev); + +void copy_font(scr_stat *scp, int operation, int font_size, u_char *font_image); +#define save_palette(scp, pal) (*biosvidsw.save_palette)((scp)->adp, pal) +#define load_palette(scp, pal) (*biosvidsw.load_palette)((scp)->adp, pal) +#define set_border(scp, col) (*biosvidsw.set_border)((scp)->adp, col) +#define get_adapter(scp) (*biosvidsw.adapter)((scp)->adp) + int add_scrn_saver(void (*this)(int)); int remove_scrn_saver(void (*this)(int)); +void sc_clear_screen(scr_stat *scp); +void sc_move_mouse(scr_stat *scp, int x, int y); +int sc_clean_up(scr_stat *scp); +void sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear); +void sc_alloc_cut_buffer(scr_stat *scp, int wait); +void sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait); + +/* scvidctl.c */ +int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, + int xsize, int ysize, int fontsize); +int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode); +int sc_set_pixel_mode(scr_stat *scp, struct tty *tp, + int xsize, int ysize, int fontsize); +int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, + struct proc *p); + #ifdef SC_SPLASH_SCREEN -void splash(int); -int splash_load(void); -int splash_unload(void); +/* splash.c */ +void scsplash(int); +int scsplash_load(scr_stat *scp); +int scsplash_unload(scr_stat *scp); #endif #endif /* !_I386_ISA_SYSCONS_H_ */ diff --git a/sys/isa/videoio.c b/sys/isa/videoio.c new file mode 100644 index 0000000..c5b84c6 --- /dev/null +++ b/sys/isa/videoio.c @@ -0,0 +1,1628 @@ +/*- + * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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. The name of the author may not 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 + * SUCH DAMAGE. + * + * $Id$ + * from: i386/isa videoio.c,v 1.1 + */ + +#include "sc.h" +#include "opt_syscons.h" + +#if NSC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/clock.h> +#include <machine/console.h> +#include <machine/md_var.h> +#include <machine/pc/bios.h> + +#include <isa/isareg.h> +#include <isa/videoio.h> + +/* this should really be in `rtc.h' */ +#define RTC_EQUIPMENT 0x14 + +/* video adapter state buffer */ +struct adp_state { + int sig; +#define V_STATE_SIG 0x736f6962 + u_char regs[V_MODE_PARAM_SIZE]; +}; +typedef struct adp_state adp_state_t; + +/* video adapter information */ +#define DCC_MONO 0 +#define DCC_CGA40 1 +#define DCC_CGA80 2 +#define DCC_EGAMONO 3 +#define DCC_EGA40 4 +#define DCC_EGA80 5 + +/* + * NOTE: `va_window' should have a virtual address, but is initialized + * with a physical address in the following table, as verify_adapter() + * will perform address conversion at run-time. + */ +static video_adapter_t adapter_init_value[] = { + { 0, KD_MONO, 0, MONO_BASE, 0xb0000, 32, 32, 0, 0, 0, 7, 0 }, + { 0, KD_CGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 }, + { 0, KD_CGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 }, + { 0, KD_EGA, 0, MONO_BASE, 0xb0000, 32, 32, 0, 0, 0, 7, 0 }, + { 0, KD_EGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 }, + { 0, KD_EGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 }, +}; + +static video_adapter_t adapter[V_MAX_ADAPTERS]; +static int adapters = 0; + +/* VGA function entries */ +static vi_init_t vid_init; +static vi_adapter_t vid_adapter; +static vi_get_info_t vid_get_info; +static vi_query_mode_t vid_query_mode; +static vi_set_mode_t vid_set_mode; +static vi_save_font_t vid_save_font; +static vi_load_font_t vid_load_font; +static vi_show_font_t vid_show_font; +static vi_save_palette_t vid_save_palette; +static vi_load_palette_t vid_load_palette; +static vi_set_border_t vid_set_border; +static vi_save_state_t vid_save_state; +static vi_load_state_t vid_load_state; +static vi_set_win_org_t vid_set_origin; +static vi_read_hw_cursor_t vid_read_hw_cursor; +static vi_set_hw_cursor_t vid_set_hw_cursor; +static vi_diag_t vid_diag; + +struct vidsw biosvidsw = { + vid_init, vid_adapter, vid_get_info, vid_query_mode, + vid_set_mode, vid_save_font, vid_load_font, vid_show_font, + vid_save_palette,vid_load_palette,vid_set_border,vid_save_state, + vid_load_state, vid_set_origin, vid_read_hw_cursor, vid_set_hw_cursor, + vid_diag, +}; + +/* VGA BIOS standard video modes */ +#define EOT (-1) +#define NA (-2) + +static video_info_t bios_vmode[] = { + /* CGA */ + { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, 0xb8000, 32, 32, 0, 32 }, + { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, 0xb8000, 32, 32, 0, 32 }, + /* EGA */ + { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, 0xb8000, 32, 32, 0, 32 }, + { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, 0xb8000, 32, 32, 0, 32 }, + /* VGA */ + { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, 0xb8000, 32, 32, 0, 32 }, + { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, 0xb0000, 32, 32, 0, 32 }, + { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 0xb8000, 32, 32, 0, 32 }, + /* MDA */ + { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, 0xb0000, 32, 32, 0, 32 }, + /* EGA */ + { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, 0xb8000, 32, 32, 0, 32 }, + /* VGA */ + { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, 0xb0000, 32, 32, 0, 32 }, + { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 0xb8000, 32, 32, 0, 32 }, + { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, 0xb0000, 32, 32, 0, 32 }, + { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, 0xb8000, 32, 32, 0, 32 }, + { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, 0xb0000, 32, 32, 0, 32 }, + { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, 0xb8000, 32, 32, 0, 32 }, + /* CGA */ + { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 2, 1, 0xb8000, 32, 32, 0, 32 }, + { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 200, 8, 8, 1, 1, 0xb8000, 32, 32, 0, 32 }, + /* EGA */ + { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 4, 4, 0xa0000, 64, 64, 0, 64 }, + { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 200, 8, 8, 4, 4, 0xa0000, 64, 64, 0, 64 }, + { M_EGAMONOAPA, V_INFO_GRAPHICS, + 640, 350, 8, 14, 4, 4, 0xa0000, 64, 64, 0, 64 }, + { M_ENHMONOAPA2,V_INFO_GRAPHICS, + 640, 350, 8, 14, 4, 4, 0xa0000, 64, 64, 0, 64 }, + { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 350, 8, 14, 2, 2, 0xa0000, 64, 64, 0, 64 }, + { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 350, 8, 14, 4, 4, 0xa0000, 64, 64, 0, 64 }, + /* VGA */ + { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 480, 8, 16, 4, 4, 0xa0000, 64, 64, 0, 64 }, + { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 480, 8, 16, 4, 4, 0xa0000, 64, 64, 0, 64 }, + { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 8, 1, 0xa0000, 64, 64, 0, 64 }, + { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 240, 8, 8, 8, 1, 0xa0000, 64, 64, 0, 64 }, + + { EOT }, +}; + +static int init_done = FALSE; +static u_char *video_mode_ptr = NULL; /* EGA/VGA */ +static u_char *video_mode_ptr2 = NULL; /* CGA/MDA */ +static u_char *mode_map[V_MODE_MAP_SIZE]; +static adp_state_t adpstate; +static adp_state_t adpstate2; +static int rows_offset = 1; + +/* local macros and functions */ +#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) + +static void map_mode_table(u_char *map[], u_char *table, int max); +static void clear_mode_map(int ad, u_char *map[], int max, int color); +static int map_mode_num(int mode); +static int map_bios_mode_num(int type, int color, int bios_mode); +static u_char *get_mode_param(int mode); +static void fill_adapter_param(int code, video_adapter_t *adp); +static int verify_adapter(video_adapter_t *adp); +#define COMP_IDENTICAL 0 +#define COMP_SIMILAR 1 +#define COMP_DIFFERENT 2 +static int comp_adpregs(u_char *buf1, u_char *buf2); + +#define PARAM_BUFSIZE 6 +static void set_font_mode(video_adapter_t *adp, u_char *buf); +static void set_normal_mode(video_adapter_t *adp, u_char *buf); + +static char *adapter_name(int type); +static void dump_adp_info(int ad, video_adapter_t *adp, int level); +static void dump_mode_info(int ad, video_info_t *info, int level); +static void dump_buffer(u_char *buf, size_t len); + +extern void generic_bcopy(const void *, void *, size_t); + +#define ISMAPPED(pa, width) \ + (((pa) <= (u_long)0x1000 - (width)) \ + || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width))) + +#define prologue(ad, flag, err) \ + if (!init_done \ + || ((ad) < 0) || ((ad) >= adapters) \ + || !(adapter[(ad)].va_flags & (flag))) \ + return (err) + +/* construct the mode parameter map */ +static void +map_mode_table(u_char *map[], u_char *table, int max) +{ + int i; + + for(i = 0; i < max; ++i) + map[i] = table + i*V_MODE_PARAM_SIZE; + for(; i < V_MODE_MAP_SIZE; ++i) + map[i] = NULL; +} + +static void +clear_mode_map(int ad, u_char *map[], int max, int color) +{ + video_info_t info; + int i; + + /* + * NOTE: we don't touch `bios_vmode[]' because it is shared + * by all adapters. + */ + for(i = 0; i < max; ++i) { + if (vid_get_info(ad, i, &info)) + continue; + if ((info.vi_flags & V_INFO_COLOR) != color) + map[i] = NULL; + } +} + +/* the non-standard video mode is based on a standard mode... */ +static int +map_mode_num(int mode) +{ + static struct { + int from; + int to; + } mode_map[] = { + { M_ENH_B80x43, M_ENH_B80x25 }, + { M_ENH_C80x43, M_ENH_C80x25 }, + { M_VGA_M80x30, M_VGA_M80x25 }, + { M_VGA_C80x30, M_VGA_C80x25 }, + { M_VGA_M80x50, M_VGA_M80x25 }, + { M_VGA_C80x50, M_VGA_C80x25 }, + { M_VGA_M80x60, M_VGA_M80x25 }, + { M_VGA_C80x60, M_VGA_C80x25 }, + { M_VGA_MODEX, M_VGA_CG320 }, + }; + int i; + + for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { + if (mode_map[i].from == mode) + return mode_map[i].to; + } + return mode; +} + +/* turn the BIOS video number into our video mode number */ +static int +map_bios_mode_num(int type, int color, int bios_mode) +{ + static int cga_modes[7] = { + M_B40x25, M_C40x25, /* 0, 1 */ + M_B80x25, M_C80x25, /* 2, 3 */ + M_BG320, M_CG320, + M_BG640, + }; + static int ega_modes[17] = { + M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */ + M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */ + M_BG320, M_CG320, + M_BG640, + M_EGAMONO80x25, /* 7 */ + 8, 9, 10, 11, 12, + M_CG320_D, + M_CG640_E, + M_ENHMONOAPA2, /* XXX: video momery > 64K */ + M_ENH_CG640, /* XXX: video momery > 64K */ + }; + static int vga_modes[20] = { + M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */ + M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */ + M_BG320, M_CG320, + M_BG640, + M_VGA_M80x25, /* 7 */ + 8, 9, 10, 11, 12, + M_CG320_D, + M_CG640_E, + M_ENHMONOAPA2, + M_ENH_CG640, + M_BG640x480, M_CG640x480, + M_VGA_CG320, + }; + + switch (type) { + + case KD_VGA: + if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0])) + return vga_modes[bios_mode]; + else if (color) + return M_VGA_C80x25; + else + return M_VGA_M80x25; + break; + + case KD_EGA: + if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0])) + return ega_modes[bios_mode]; + else if (color) + return M_ENH_C80x25; + else + return M_EGAMONO80x25; + break; + + case KD_CGA: + if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0])) + return cga_modes[bios_mode]; + else + return M_C80x25; + break; + + case KD_MONO: + case KD_HERCULES: + return M_EGAMONO80x25; /* XXX: this name is confusing */ + + default: + break; + } + return -1; +} + +/* look up a parameter table entry */ +static u_char +*get_mode_param(int mode) +{ + if (mode >= V_MODE_MAP_SIZE) + mode = map_mode_num(mode); + if (mode < V_MODE_MAP_SIZE) + return mode_map[mode]; + else + return NULL; +} + +static void +fill_adapter_param(int code, video_adapter_t *adp) +{ + static struct { + int primary; + int secondary; + } dcc[] = { + { DCC_MONO, DCC_EGA40 /* CGA monitor */ }, + { DCC_MONO, DCC_EGA80 /* CGA monitor */ }, + { DCC_MONO, DCC_EGA80 /* CGA emulation */ }, + { DCC_MONO, DCC_EGA80 }, + { DCC_CGA40, DCC_EGAMONO }, + { DCC_CGA80, DCC_EGAMONO }, + { DCC_EGA40 /* CGA monitor */, DCC_MONO}, + { DCC_EGA80 /* CGA monitor */, DCC_MONO}, + { DCC_EGA80 /* CGA emulation */,DCC_MONO }, + { DCC_EGA80, DCC_MONO }, + { DCC_EGAMONO, DCC_CGA40 }, + { DCC_EGAMONO, DCC_CGA40 }, + }; + + if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) { + adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; + adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; + } else { + adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary]; + adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary]; + } +} + +static int +verify_adapter(video_adapter_t *adp) +{ + u_int32_t buf; + u_short v; + u_int32_t p; + + buf = BIOS_PADDRTOVADDR(adp->va_window); + v = readw(buf); + writew(buf, 0xA55A); + if (readw(buf) != 0xA55A) + return 1; + writew(buf, v); + + switch (adp->va_type) { + + case KD_EGA: + outb(adp->va_crtc_addr, 7); + if (inb(adp->va_crtc_addr) == 7) { + adp->va_type = KD_VGA; + adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE; + } + adp->va_flags |= V_ADP_STATELOAD | V_ADP_FONT | V_ADP_BORDER; + /* the color adapter may be in the 40x25 mode... XXX */ + +#ifdef __i386__ + /* get the BIOS video mode pointer */ + p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8); + p = BIOS_SADDRTOLADDR(p); + if (ISMAPPED(p, sizeof(u_int32_t))) { + p = *(u_int32_t *)BIOS_PADDRTOVADDR(p); + p = BIOS_SADDRTOLADDR(p); + if (ISMAPPED(p, V_MODE_PARAM_SIZE)) + video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p); + } +#endif + break; + + case KD_CGA: + adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER; + /* may be in the 40x25 mode... XXX */ + break; + + case KD_MONO: + break; + } + + return 0; +} + +/* compare two parameter table entries */ +static int +comp_adpregs(u_char *buf1, u_char *buf2) +{ + static struct { + u_char mask; + } params[V_MODE_PARAM_SIZE] = { + 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */ + 0x00, 0x00, /* page length */ + 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */ + 0xf3, /* misc register */ + 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */ + 0xff, 0xff, 0xff, 0x7f, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x7f, 0xff, 0xff, + 0x7f, 0xff, 0xff, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */ + 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */ + 0xff, 0xff, 0xff, 0xff, + }; + int identical = TRUE; + int i; + + if ((buf1 == NULL) || (buf2 == NULL)) + return COMP_DIFFERENT; + + for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { + if (params[i].mask == 0) /* don't care */ + continue; + if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) + return COMP_DIFFERENT; + if (buf1[i] != buf2[i]) + identical = FALSE; + } + return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; +} + +/* exported functions */ + +/* all adapters */ +static int +vid_init(void) +{ + video_adapter_t *adp; + video_info_t info; + u_char *mp; + int i; + + /* do this test only once */ + if (init_done) + return adapters; + init_done = TRUE; + + /* + * Locate display adapters. + * The AT architecture supports upto two adapters. `syscons' allows + * the following combinations of adapters: + * 1) MDA + CGA + * 2) MDA + EGA/VGA color + * 3) CGA + EGA/VGA mono + * Note that `syscons' doesn't bother with MCGA as it is only + * avaiable for low end PS/2 models which has 80286 or earlier CPUs, + * thus, they are not running FreeBSD! + * When there are two adapaters in the system, one becomes `primary' + * and the other `secondary'. The EGA adapter has a set of DIP + * switches on board for this information and the EGA BIOS copies + * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88). + * The VGA BIOS has more sophisticated mechanism and has this + * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains + * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH. + */ + + /* check rtc and BIOS date area */ + /* + * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy + * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are + * zeros for EGA and VGA. However, the EGA/VGA BIOS will set + * these bits in BIOSDATA_EQUIPMENT according to the monitor + * type detected. + */ +#ifdef __i386__ + switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ + case 0: + /* EGA/VGA */ + fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f, + adapter); + break; + case 1: + /* CGA 40x25 */ + /* FIXME: switch to the 80x25 mode? XXX */ + adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40]; + adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; + break; + case 2: + /* CGA 80x25 */ + adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80]; + adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; + break; + case 3: + /* MDA */ + adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; + adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; + break; + } +#else + /* EGA/VGA */ + fill_adapter_param(-1, adapter); +#endif + + adapters = 0; + if (verify_adapter(&adapter[V_ADP_SECONDARY]) == 0) { + ++adapters; + adapter[V_ADP_SECONDARY].va_mode = + adapter[V_ADP_SECONDARY].va_initial_mode = + map_bios_mode_num(adapter[V_ADP_SECONDARY].va_type, + adapter[V_ADP_SECONDARY].va_flags & V_ADP_COLOR, + adapter[V_ADP_SECONDARY].va_initial_bios_mode); + } else { + adapter[V_ADP_SECONDARY].va_type = -1; + } + if (verify_adapter(&adapter[V_ADP_PRIMARY]) == 0) { + ++adapters; +#ifdef __i386__ + adapter[V_ADP_PRIMARY].va_initial_bios_mode = + *(u_int8_t *)BIOS_PADDRTOVADDR(0x449); +#else + adapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; +#endif + adapter[V_ADP_PRIMARY].va_mode = + adapter[V_ADP_PRIMARY].va_initial_mode = + map_bios_mode_num(adapter[V_ADP_PRIMARY].va_type, + adapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR, + adapter[V_ADP_PRIMARY].va_initial_bios_mode); + } else { + adapter[V_ADP_PRIMARY] = adapter[V_ADP_SECONDARY]; + adapter[V_ADP_SECONDARY].va_type = -1; + } + if (adapters == 0) + return adapters; + adapter[V_ADP_PRIMARY].va_index = V_ADP_PRIMARY; + adapter[V_ADP_SECONDARY].va_index = V_ADP_SECONDARY; + +#if 0 + /* + * We cannot have two video adapter of the same type; there must be + * only one of color or mono adapter, or one each of them. + */ + if (adapters > 1) { + if (!((adapter[0].va_flags ^ adapter[1].va_flags) & V_ADP_COLOR)) + /* we have two mono or color adapters!! */ + return (adapters = 0); + } +#endif + + /* + * Ensure a zero start address. This is mainly to recover after + * switching from pcvt using userconfig(). The registers are w/o + * for old hardware so it's too hard to relocate the active screen + * memory. + * This must be done before vid_save_state() for VGA. + */ + outb(adapter[V_ADP_PRIMARY].va_crtc_addr, 12); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr, 13); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); + + /* the video mode parameter table in EGA/VGA BIOS */ + /* NOTE: there can be only one EGA/VGA, wheather color or mono, + * recognized by the video BIOS. + */ + if ((adapter[V_ADP_PRIMARY].va_type == KD_EGA) || + (adapter[V_ADP_PRIMARY].va_type == KD_VGA)) { + adp = &adapter[V_ADP_PRIMARY]; + } else if ((adapter[V_ADP_SECONDARY].va_type == KD_EGA) || + (adapter[V_ADP_SECONDARY].va_type == KD_VGA)) { + adp = &adapter[V_ADP_SECONDARY]; + } else { + adp = NULL; + } + bzero(mode_map, sizeof(mode_map)); + if (adp != NULL) { + if (adp->va_type == KD_VGA) { + vid_save_state(adp - adapter, &adpstate, sizeof(adpstate)); + if (video_mode_ptr == NULL) { + mode_map[map_mode_num(adp->va_initial_mode)] = adpstate.regs; + rows_offset = 1; + } else { + /* discard the table if we are not familiar with it... */ + map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); + mp = get_mode_param(adp->va_initial_mode); + if (mp != NULL) + bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs)); + switch (comp_adpregs(adpstate.regs, mp)) { + case COMP_IDENTICAL: + /* + * OK, this parameter table looks reasonably familiar + * to us... + */ + /* + * This is a kludge for Toshiba DynaBook SS433 + * whose BIOS video mode table entry has the actual # + * of rows at the offset 1; BIOSes from other + * manufacturers store the # of rows - 1 there. XXX + */ + rows_offset = adpstate.regs[1] + 1 - mp[1]; + break; + + case COMP_SIMILAR: + /* + * Not exactly the same, but similar enough to be + * trusted. However, use the saved register values + * for the initial mode and other modes which are + * based on the initial mode. + */ + mode_map[map_mode_num(adp->va_initial_mode)] = + adpstate.regs; + rows_offset = adpstate.regs[1] + 1 - mp[1]; + adpstate.regs[1] -= rows_offset - 1; + break; + + case COMP_DIFFERENT: + default: + /* + * Don't use the paramter table in BIOS. It doesn't + * look familiar to us. Video mode switching is allowed + * only if the new mode is the same as or based on + * the initial mode. + */ + video_mode_ptr = NULL; + bzero(mode_map, sizeof(mode_map)); + mode_map[map_mode_num(adp->va_initial_mode)] = + adpstate.regs; + rows_offset = 1; + break; + } + } + adp->va_flags |= V_ADP_MODECHANGE; + } else if (adp->va_type == KD_EGA) { + if (video_mode_ptr == NULL) { + adp->va_flags &= ~V_ADP_FONT; + rows_offset = 1; + } else { + map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1); + /* XXX how can one validate the EGA table... */ + mp = get_mode_param(adp->va_initial_mode); + if (mp != NULL) { + adp->va_flags |= V_ADP_MODECHANGE; + rows_offset = 1; + } else { + /* + * This is serious. We will not be able to switch video + * modes at all... + */ + adp->va_flags &= ~V_ADP_FONT; + video_mode_ptr = NULL; + bzero(mode_map, sizeof(mode_map)); + rows_offset = 1; + } + } + } + } + + /* remove conflicting modes if we have more than one adapter */ + if (adapters > 1) { + for (i = 0; i < adapters; ++i) { + if (!(adapter[i].va_flags & V_ADP_MODECHANGE)) + continue; + clear_mode_map(i, mode_map, M_VGA_CG320 + 1, + (adapter[i].va_flags & V_ADP_COLOR) ? + V_INFO_COLOR : 0); + } + } + + /* buffer address */ + vid_get_info(V_ADP_PRIMARY, + adapter[V_ADP_PRIMARY].va_initial_mode, &info); + adapter[V_ADP_PRIMARY].va_window = BIOS_PADDRTOVADDR(info.vi_window); + adapter[V_ADP_PRIMARY].va_window_size = info.vi_window_size; + adapter[V_ADP_PRIMARY].va_window_gran = info.vi_window_gran; + adapter[V_ADP_PRIMARY].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); + adapter[V_ADP_PRIMARY].va_buffer_size = info.vi_buffer_size; + if (adapters > 1) { + vid_get_info(V_ADP_SECONDARY, + adapter[V_ADP_SECONDARY].va_initial_mode, &info); + adapter[V_ADP_SECONDARY].va_window = BIOS_PADDRTOVADDR(info.vi_window); + adapter[V_ADP_SECONDARY].va_window_size = info.vi_window_size; + adapter[V_ADP_SECONDARY].va_window_gran = info.vi_window_gran; + adapter[V_ADP_SECONDARY].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); + adapter[V_ADP_SECONDARY].va_buffer_size = info.vi_buffer_size; + } + + /* + * XXX: we should verify the following values for the primary adapter... + * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463); + * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02) + * ? 0 : V_ADP_COLOR; + * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a); + * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484); + * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485); + * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c); + */ + + return adapters; +} + +/* all adapters */ +static video_adapter_t +*vid_adapter(int ad) +{ + if (!init_done) + return NULL; + if ((ad < 0) || (ad >= adapters)) + return NULL; + return &adapter[ad]; +} + +/* all adapters */ +static int +vid_get_info(int ad, int mode, video_info_t *info) +{ + int i; + + if (!init_done) + return 1; + if ((ad < 0) || (ad >= adapters)) + return 1; + + if (adapter[ad].va_flags & V_ADP_MODECHANGE) { + /* + * If the parameter table entry for this mode is not found, + * the mode is not supported... + */ + if (get_mode_param(mode) == NULL) + return 1; + } else { + /* + * Even if we don't support video mode switching on this adapter, + * the information on the initial (thus current) video mode + * should be made available. + */ + if (mode != adapter[ad].va_initial_mode) + return 1; + } + + for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { + if (bios_vmode[i].vi_mode == NA) + continue; + if (mode == bios_vmode[i].vi_mode) { + *info = bios_vmode[i]; + return 0; + } + } + return 1; +} + +/* all adapters */ +static int +vid_query_mode(int ad, video_info_t *info) +{ + video_info_t buf; + int i; + + if (!init_done) + return -1; + if ((ad < 0) || (ad >= adapters)) + return -1; + + for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { + if (bios_vmode[i].vi_mode == NA) + continue; + + if ((info->vi_width != 0) + && (info->vi_width != bios_vmode[i].vi_width)) + continue; + if ((info->vi_height != 0) + && (info->vi_height != bios_vmode[i].vi_height)) + continue; + if ((info->vi_cwidth != 0) + && (info->vi_cwidth != bios_vmode[i].vi_cwidth)) + continue; + if ((info->vi_cheight != 0) + && (info->vi_cheight != bios_vmode[i].vi_cheight)) + continue; + if ((info->vi_depth != 0) + && (info->vi_depth != bios_vmode[i].vi_depth)) + continue; + if ((info->vi_planes != 0) + && (info->vi_planes != bios_vmode[i].vi_planes)) + continue; + /* XXX: should check pixel format, memory model */ + if ((info->vi_flags != 0) + && (info->vi_flags != bios_vmode[i].vi_flags)) + continue; + + /* verify if this mode is supported on this adapter */ + if (vid_get_info(ad, bios_vmode[i].vi_mode, &buf)) + continue; + return bios_vmode[i].vi_mode; + } + return -1; +} + +/* EGA/VGA */ +static int +vid_set_mode(int ad, int mode) +{ + video_info_t info; + adp_state_t params; + + prologue(ad, V_ADP_MODECHANGE, 1); + + if (vid_get_info(ad, mode, &info)) + return 1; + params.sig = V_STATE_SIG; + bcopy(get_mode_param(mode), params.regs, sizeof(params.regs)); + + switch (mode) { + case M_VGA_C80x60: case M_VGA_M80x60: + params.regs[2] = 0x08; + params.regs[19] = 0x47; + goto special_480l; + + case M_VGA_C80x30: case M_VGA_M80x30: + params.regs[19] = 0x4f; +special_480l: + params.regs[9] |= 0xc0; + params.regs[16] = 0x08; + params.regs[17] = 0x3e; + params.regs[26] = 0xea; + params.regs[28] = 0xdf; + params.regs[31] = 0xe7; + params.regs[32] = 0x04; + goto setup_mode; + + case M_ENH_C80x43: case M_ENH_B80x43: + params.regs[28] = 87; + goto special_80x50; + + case M_VGA_C80x50: case M_VGA_M80x50: +special_80x50: + params.regs[2] = 8; + params.regs[19] = 7; + goto setup_mode; + + case M_VGA_C40x25: case M_VGA_C80x25: + case M_VGA_M80x25: + case M_B40x25: case M_C40x25: + case M_B80x25: case M_C80x25: + case M_ENH_B40x25: case M_ENH_C40x25: + case M_ENH_B80x25: case M_ENH_C80x25: + case M_EGAMONO80x25: + +setup_mode: + vid_load_state(ad, ¶ms); + break; + + case M_VGA_MODEX: + /* "unchain" the VGA mode */ + params.regs[5-1+0x04] &= 0xf7; + params.regs[5-1+0x04] |= 0x04; + /* turn off doubleword mode */ + params.regs[10+0x14] &= 0xbf; + /* turn off word adressing */ + params.regs[10+0x17] |= 0x40; + /* set logical screen width */ + params.regs[10+0x13] = 80; + /* set 240 lines */ + params.regs[10+0x11] = 0x2c; + params.regs[10+0x06] = 0x0d; + params.regs[10+0x07] = 0x3e; + params.regs[10+0x10] = 0xea; + params.regs[10+0x11] = 0xac; + params.regs[10+0x12] = 0xdf; + params.regs[10+0x15] = 0xe7; + params.regs[10+0x16] = 0x06; + /* set vertical sync polarity to reflect aspect ratio */ + params.regs[9] = 0xe3; + goto setup_grmode; + + case M_BG320: case M_CG320: case M_BG640: + case M_CG320_D: case M_CG640_E: + case M_CG640x350: case M_ENH_CG640: + case M_BG640x480: case M_CG640x480: case M_VGA_CG320: + +setup_grmode: + vid_load_state(ad, ¶ms); + break; + + default: + return 1; + } + + adapter[ad].va_mode = mode; + adapter[ad].va_flags &= ~V_ADP_COLOR; + adapter[ad].va_flags |= + (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; + adapter[ad].va_crtc_addr = + (adapter[ad].va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE; + adapter[ad].va_window = BIOS_PADDRTOVADDR(info.vi_window); + adapter[ad].va_window_size = info.vi_window_size; + adapter[ad].va_window_gran = info.vi_window_gran; + if (info.vi_buffer_size == 0) { + adapter[ad].va_buffer = 0; + adapter[ad].va_buffer_size = 0; + } else { + adapter[ad].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); + adapter[ad].va_buffer_size = info.vi_buffer_size; + } + + return 0; +} + +static void +set_font_mode(video_adapter_t *adp, u_char *buf) +{ + u_char *mp; + int s; + + s = splhigh(); + + /* save register values */ + if (adp->va_type == KD_VGA) { + outb(TSIDX, 0x02); buf[0] = inb(TSREG); + outb(TSIDX, 0x04); buf[1] = inb(TSREG); + outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); + outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); + outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); + inb(adp->va_crtc_addr + 6); + outb(ATC, 0x10); buf[5] = inb(ATC + 1); + } else /* if (adp->va_type == KD_EGA) */ { + /* + * EGA cannot be read; copy parameters from the mode parameter + * table. + */ + mp = get_mode_param(adp->va_mode); + buf[0] = mp[5 + 0x02 - 1]; + buf[1] = mp[5 + 0x04 - 1]; + buf[2] = mp[55 + 0x04]; + buf[3] = mp[55 + 0x05]; + buf[4] = mp[55 + 0x06]; + buf[5] = mp[35 + 0x10]; + } + + /* setup vga for loading fonts */ + inb(adp->va_crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01); + inb(adp->va_crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + +#if SLOW_VGA +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x01); +#endif + outb(TSIDX, 0x02); outb(TSREG, 0x04); + outb(TSIDX, 0x04); outb(TSREG, 0x07); +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x03); +#endif + outb(GDCIDX, 0x04); outb(GDCREG, 0x02); + outb(GDCIDX, 0x05); outb(GDCREG, 0x00); + outb(GDCIDX, 0x06); outb(GDCREG, 0x04); +#else +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0100); +#endif + outw(TSIDX, 0x0402); + outw(TSIDX, 0x0704); +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0300); +#endif + outw(GDCIDX, 0x0204); + outw(GDCIDX, 0x0005); + outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ +#endif + + splx(s); +} + +static void +set_normal_mode(video_adapter_t *adp, u_char *buf) +{ + int s; + + s = splhigh(); + + /* setup vga for normal operation mode again */ + inb(adp->va_crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x10); outb(ATC, buf[5]); + inb(adp->va_crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + +#if SLOW_VGA +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x01); +#endif + outb(TSIDX, 0x02); outb(TSREG, buf[0]); + outb(TSIDX, 0x04); outb(TSREG, buf[1]); +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x03); +#endif + outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); + outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); + if (adp->va_crtc_addr == MONO_BASE) { + outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); + } else { + outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); + } +#else +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0100); +#endif + outw(TSIDX, 0x0002 | (buf[0] << 8)); + outw(TSIDX, 0x0004 | (buf[1] << 8)); +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0300); +#endif + outw(GDCIDX, 0x0004 | (buf[2] << 8)); + outw(GDCIDX, 0x0005 | (buf[3] << 8)); + if (adp->va_crtc_addr == MONO_BASE) + outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); + else + outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); +#endif + + splx(s); +} + +/* EGA/VGA */ +static int +vid_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count) +{ + u_char buf[PARAM_BUFSIZE]; + u_char val = 0; + u_int32_t segment; + int c; + int s; + + prologue(ad, V_ADP_FONT, 1); + + if (fontsize < 14) { + /* FONT_8 */ + fontsize = 8; + } else if (fontsize >= 32) { + fontsize = 32; + } else if (fontsize >= 16) { + /* FONT_16 */ + fontsize = 16; + } else { + /* FONT_14 */ + fontsize = 14; + } + + if (page < 0 || page >= 8) + return 1; + segment = VIDEOMEM + 0x4000*page; + if (page > 3) + segment -= 0xe000; + + if (adapter[ad].va_type == KD_VGA) { /* what about EGA? XXX */ + s = splhigh(); + outb(TSIDX, 0x00); outb(TSREG, 0x01); + outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ + outb(TSIDX, 0x01); outb(TSREG, val | 0x20); + outb(TSIDX, 0x00); outb(TSREG, 0x03); + splx(s); + } + + set_font_mode(&adapter[ad], buf); + if (fontsize == 32) { + memcpy_fromio(data, BIOS_PADDRTOVADDR(segment + ch*32), + fontsize*count); + } else { + for (c = ch; count > 0; ++c, --count) { + memcpy_fromio(data, BIOS_PADDRTOVADDR(segment + c*32), + fontsize); + data += fontsize; + } + } + set_normal_mode(&adapter[ad], buf); + + if (adapter[ad].va_type == KD_VGA) { + s = splhigh(); + outb(TSIDX, 0x00); outb(TSREG, 0x01); + outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); + splx(s); + } + + return 0; +} + +/* EGA/VGA */ +static int +vid_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count) +{ + u_char buf[PARAM_BUFSIZE]; + u_char val = 0; + u_int32_t segment; + int c; + int s; + + prologue(ad, V_ADP_FONT, 1); + + if (fontsize < 14) { + /* FONT_8 */ + fontsize = 8; + } else if (fontsize >= 32) { + fontsize = 32; + } else if (fontsize >= 16) { + /* FONT_16 */ + fontsize = 16; + } else { + /* FONT_14 */ + fontsize = 14; + } + + if (page < 0 || page >= 8) + return 1; + segment = VIDEOMEM + 0x4000*page; + if (page > 3) + segment -= 0xe000; + + if (adapter[ad].va_type == KD_VGA) { /* what about EGA? XXX */ + s = splhigh(); + outb(TSIDX, 0x00); outb(TSREG, 0x01); + outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ + outb(TSIDX, 0x01); outb(TSREG, val | 0x20); + outb(TSIDX, 0x00); outb(TSREG, 0x03); + splx(s); + } + + set_font_mode(&adapter[ad], buf); + if (fontsize == 32) { + memcpy_toio(BIOS_PADDRTOVADDR(segment + ch*32), data, + fontsize*count); + } else { + for (c = ch; count > 0; ++c, --count) { + memcpy_toio(BIOS_PADDRTOVADDR(segment + c*32), data, + fontsize); + data += fontsize; + } + } + set_normal_mode(&adapter[ad], buf); + + if (adapter[ad].va_type == KD_VGA) { + s = splhigh(); + outb(TSIDX, 0x00); outb(TSREG, 0x01); + outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); + splx(s); + } + + return 0; +} + +/* EGA/VGA */ +static int +vid_show_font(int ad, int page) +{ + static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f }; + int s; + + prologue(ad, V_ADP_FONT, 1); + if (page < 0 || page >= 8) + return 1; + + s = splhigh(); + outb(TSIDX, 0x03); outb(TSREG, cg[page]); + splx(s); + + return 0; +} + +/* VGA */ +static int +vid_save_palette(int ad, u_char *palette) +{ + int i; + + prologue(ad, V_ADP_PALETTE, 1); + + /* + * We store 8 bit values in the palette buffer, while the standard + * VGA has 6 bit DAC . + */ + outb(PALRADR, 0x00); + for (i = 0; i < 256*3; ++i) + palette[i] = inb(PALDATA) << 2; + inb(adapter[ad].va_crtc_addr + 6); /* reset flip/flop */ + return 0; +} + +/* VGA */ +static int +vid_load_palette(int ad, u_char *palette) +{ + int i; + + prologue(ad, V_ADP_PALETTE, 1); + + outb(PIXMASK, 0xff); /* no pixelmask */ + outb(PALWADR, 0x00); + for (i = 0; i < 256*3; ++i) + outb(PALDATA, palette[i] >> 2); + inb(adapter[ad].va_crtc_addr + 6); /* reset flip/flop */ + outb(ATC, 0x20); /* enable palette */ + return 0; +} + +/* CGA/EGA/VGA */ +static int +vid_set_border(int ad, int color) +{ + prologue(ad, V_ADP_BORDER, 1); + + switch (adapter[ad].va_type) { + case KD_EGA: + case KD_VGA: + inb(adapter[ad].va_crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x31); outb(ATC, color & 0xff); + break; + case KD_CGA: + outb(adapter[ad].va_crtc_addr + 5, color & 0x0f); /* color select register */ + break; + case KD_MONO: + case KD_HERCULES: + default: + break; + } + return 0; +} + +/* VGA */ +static int +vid_save_state(int ad, void *p, size_t size) +{ + video_info_t info; + u_char *buf; + int crtc_addr; + int i, j; + int s; + + if (size == 0) { + /* return the required buffer size */ + prologue(ad, V_ADP_STATESAVE, 0); + return sizeof(adp_state_t); + } else { + prologue(ad, V_ADP_STATESAVE, 1); + if (size < sizeof(adp_state_t)) + return 1; + } + + ((adp_state_t *)p)->sig = V_STATE_SIG; + buf = ((adp_state_t *)p)->regs; + bzero(buf, V_MODE_PARAM_SIZE); + crtc_addr = adapter[ad].va_crtc_addr; + + s = splhigh(); + + outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ + for (i = 0, j = 5; i < 4; i++) { + outb(TSIDX, i + 1); + buf[j++] = inb(TSREG); + } + buf[9] = inb(MISC + 10); /* dot-clock */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ + + for (i = 0, j = 10; i < 25; i++) { /* crtc */ + outb(crtc_addr, i); + buf[j++] = inb(crtc_addr + 1); + } + for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */ + inb(crtc_addr + 6); /* reset flip-flop */ + outb(ATC, i); + buf[j++] = inb(ATC + 1); + } + for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */ + outb(GDCIDX, i); + buf[j++] = inb(GDCREG); + } + inb(crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + + splx(s); + +#if 1 + if (vid_get_info(ad, adapter[ad].va_mode, &info) == 0) { + if (info.vi_flags & V_INFO_GRAPHICS) { + buf[0] = info.vi_width/info.vi_cwidth; /* COLS */ + buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */ + } else { + buf[0] = info.vi_width; /* COLS */ + buf[1] = info.vi_height - 1; /* ROWS */ + } + buf[2] = info.vi_cheight; /* POINTS */ + } else { + /* XXX: shouldn't be happening... */ + printf("video#%d: failed to obtain mode info. (vid_save_state())\n", + ad); + } +#else + buf[0] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a); /* COLS */ + buf[1] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x484); /* ROWS */ + buf[2] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x485); /* POINTS */ + buf[3] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44c); + buf[4] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44d); +#endif + + return 0; +} + +/* EGA/VGA */ +static int +vid_load_state(int ad, void *p) +{ + u_char *buf; + int crtc_addr; + int s; + int i; + + prologue(ad, V_ADP_STATELOAD, 1); + if (((adp_state_t *)p)->sig != V_STATE_SIG) + return 1; + + buf = ((adp_state_t *)p)->regs; + crtc_addr = adapter[ad].va_crtc_addr; + + s = splhigh(); + + outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ + for (i = 0; i < 4; ++i) { /* program sequencer */ + outb(TSIDX, i + 1); + outb(TSREG, buf[i + 5]); + } + outb(MISC, buf[9]); /* set dot-clock */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ + outb(crtc_addr, 0x11); + outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F); + for (i = 0; i < 25; ++i) { /* program crtc */ + outb(crtc_addr, i); + outb(crtc_addr + 1, buf[i + 10]); + } + inb(crtc_addr+6); /* reset flip-flop */ + for (i = 0; i < 20; ++i) { /* program attribute ctrl */ + outb(ATC, i); + outb(ATC, buf[i + 35]); + } + for (i = 0; i < 9; ++i) { /* program graph data ctrl */ + outb(GDCIDX, i); + outb(GDCREG, buf[i + 55]); + } + inb(crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + +#ifdef __i386__ + if (ad == V_ADP_PRIMARY) { + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a) = buf[0]; /* COLS */ + *(u_int8_t *)BIOS_PADDRTOVADDR(0x484) = buf[1] + rows_offset - 1; /* ROWS */ + *(u_int8_t *)BIOS_PADDRTOVADDR(0x485) = buf[2]; /* POINTS */ +#if 0 + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44c) = buf[3]; + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44d) = buf[4]; +#endif + } +#endif + + splx(s); + return 0; +} + +/* all */ +static int +vid_set_origin(int ad, off_t offset) +{ + /* + * The standard video modes do not require window mapping; + * always return error. + */ + return 1; +} + +/* all */ +static int +vid_read_hw_cursor(int ad, int *col, int *row) +{ + video_info_t info; + u_int16_t off; + + if (!init_done) + return 1; + if ((ad < 0) || (ad >= adapters)) + return 1; + + (*biosvidsw.get_info)(ad, adapter[ad].va_mode, &info); + if (info.vi_flags & V_INFO_GRAPHICS) + return 1; + + outb(adapter[ad].va_crtc_addr, 14); + off = inb(adapter[ad].va_crtc_addr + 1); + outb(adapter[ad].va_crtc_addr, 15); + off = (off << 8) | inb(adapter[ad].va_crtc_addr + 1); + + *row = off / info.vi_width; + *col = off % info.vi_width; + + return 0; +} + +/* all */ +static int +vid_set_hw_cursor(int ad, int col, int row) +{ + video_info_t info; + u_int16_t off; + + if (!init_done) + return 1; + if ((ad < 0) || (ad >= adapters)) + return 1; + + (*biosvidsw.get_info)(ad, adapter[ad].va_mode, &info); + if (info.vi_flags & V_INFO_GRAPHICS) + return 1; + + if ((col == -1) || (row == -1)) + off = 0xffff; + else + off = row*info.vi_width + col; + outb(adapter[ad].va_crtc_addr, 14); + outb(adapter[ad].va_crtc_addr + 1, off >> 8); + outb(adapter[ad].va_crtc_addr, 15); + outb(adapter[ad].va_crtc_addr + 1, off & 0x00ff); + + return 0; +} + +static char +*adapter_name(int type) +{ + static struct { + int type; + char *name; + } names[] = { + { KD_MONO, "MDA" }, + { KD_HERCULES, "Hercules" }, + { KD_CGA, "CGA" }, + { KD_EGA, "EGA" }, + { KD_VGA, "VGA" }, + { KD_PC98, "PC-98xx" }, + { -1, "Unknown" }, + }; + int i; + + for (i = 0; names[i].type != -1; ++i) + if (names[i].type == type) + break; + return names[i].name; +} + +static void +dump_adp_info(int ad, video_adapter_t *adp, int level) +{ + if (level <= 0) + return; + + printf("video#%d: adapter type:%s (%d), flags:0x%x, CRTC:0x%x\n", + ad, adapter_name(adp->va_type), adp->va_type, + adp->va_flags, adp->va_crtc_addr); + printf("video#%d: init mode:%d, bios mode:%d, current mode:%d\n", + ad, adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode); + printf("video#%d: window:0x%x size:%dk gran:%dk, buf:0x%x size:%dk\n", + ad, + adp->va_window, (int)adp->va_window_size, (int)adp->va_window_gran, + adp->va_buffer, (int)adp->va_buffer_size); +} + +static void +dump_mode_info(int ad, video_info_t *info, int level) +{ + if (level <= 0) + return; + + printf("video#%d: mode:%d, flags:0x%x ", + ad, info->vi_mode, info->vi_flags); + if (info->vi_flags & V_INFO_GRAPHICS) + printf("G %dx%dx%d, %d plane(s), font:%dx%d, ", + info->vi_width, info->vi_height, + info->vi_depth, info->vi_planes, + info->vi_cwidth, info->vi_cheight); + else + printf("T %dx%d, font:%dx%d, ", + info->vi_width, info->vi_height, + info->vi_cwidth, info->vi_cheight); + printf("win:0x%x\n", info->vi_window); +} + +static void +dump_buffer(u_char *buf, size_t len) +{ + int i; + + for(i = 0; i < len;) { + printf("%02x ", buf[i]); + if ((++i % 16) == 0) + printf("\n"); + } +} + +static int +vid_diag(int level) +{ + video_info_t info; + u_char *mp; + int ad; + int i; + + if (!init_done) + return 1; + +#ifdef __i386__ + if (level > 0) { + printf("video: RTC equip. code:0x%02x, DCC code:0x%02x\n", + rtcin(RTC_EQUIPMENT), *(u_int8_t *)BIOS_PADDRTOVADDR(0x488)); + printf("video: CRTC:0x%x, video option:0x%02x, ", + *(u_int16_t *)BIOS_PADDRTOVADDR(0x463), + *(u_int8_t *)BIOS_PADDRTOVADDR(0x487)); + printf("rows:%d, cols:%d, font height:%d\n", + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a), + *(u_int8_t *)BIOS_PADDRTOVADDR(0x484) + 1, + *(u_int8_t *)BIOS_PADDRTOVADDR(0x485)); + printf("video: param table EGA/VGA:%p, CGA/MDA:%p\n", + video_mode_ptr, video_mode_ptr2); + printf("video: rows_offset:%d\n", rows_offset); + } +#endif + + for (ad = 0; ad < adapters; ++ad) { + dump_adp_info(ad, &adapter[ad], level); + + if (!(adapter[ad].va_flags & V_ADP_MODECHANGE)) { + vid_get_info(ad, adapter[ad].va_initial_mode, &info); + dump_mode_info(ad, &info, level); + } else { + for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { + if (bios_vmode[i].vi_mode == NA) + continue; + if (get_mode_param(bios_vmode[i].vi_mode) == NULL) + continue; + dump_mode_info(ad, &bios_vmode[i], level); + } + } + if ((adapter[ad].va_type != KD_EGA) && (adapter[ad].va_type != KD_VGA)) + continue; + + if (video_mode_ptr == NULL) + printf("video#%d: WARNING: video mode switching is not fully supported on this adapter\n", ad); + + if (level <= 0) + continue; + + if (adapter[ad].va_type == KD_VGA) { + printf("VGA parameters upon power-up\n"); + dump_buffer(adpstate.regs, sizeof(adpstate.regs)); + printf("VGA parameters in BIOS for mode %d\n", + adapter[ad].va_initial_mode); + dump_buffer(adpstate2.regs, sizeof(adpstate2.regs)); + } + + mp = get_mode_param(adapter[ad].va_initial_mode); + if (mp == NULL) /* this shouldn't be happening */ + continue; + printf("EGA/VGA parameters to be used for mode %d\n", + adapter[ad].va_initial_mode); + dump_buffer(mp, V_MODE_PARAM_SIZE); + } + + return 0; +} + +#endif /* NSC > 0 */ diff --git a/sys/isa/videoio.h b/sys/isa/videoio.h new file mode 100644 index 0000000..d004478 --- /dev/null +++ b/sys/isa/videoio.h @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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. The name of the author may not 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 + * SUCH DAMAGE. + * + * $Id$ + * from: i386/isa/videoio.h,v 1.1 + */ + +#ifndef _I386_ISA_VIDEOIO_H_ +#define _I386_ISA_VIDEOIO_H_ + +#ifdef KERNEL + +#define V_MAX_ADAPTERS 2 + +#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1) +#define V_MODE_PARAM_SIZE 64 + +/* physical addresses */ +#define MONO_BUF BIOS_PADDRTOVADDR(0xb0000) +#define CGA_BUF BIOS_PADDRTOVADDR(0xb8000) +#define GRAPHICS_BUF BIOS_PADDRTOVADDR(0xa0000) +#define VIDEOMEM 0x000A0000 + +/* I/O port addresses */ +#define MONO_BASE 0x3B4 /* crt controller base mono */ +#define COLOR_BASE 0x3D4 /* crt controller base color */ +#define MISC 0x3C2 /* misc output register */ +#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 */ + +/* video function table */ +typedef int vi_init_t(void); +typedef video_adapter_t *vi_adapter_t(int ad); +typedef int vi_get_info_t(int ad, int mode, video_info_t *info); +typedef int vi_query_mode_t(int ad, video_info_t *info); +typedef int vi_set_mode_t(int ad, int mode); +typedef int vi_save_font_t(int ad, int page, int size, u_char *data, + int c, int count); +typedef int vi_load_font_t(int ad, int page, int size, u_char *data, + int c, int count); +typedef int vi_show_font_t(int ad, int page); +typedef int vi_save_palette_t(int ad, u_char *palette); +typedef int vi_load_palette_t(int ad, u_char *palette); +typedef int vi_set_border_t(int ad, int border); +typedef int vi_save_state_t(int ad, void *p, size_t size); +typedef int vi_load_state_t(int ad, void *p); +typedef int vi_set_win_org_t(int ad, off_t offset); +typedef int vi_read_hw_cursor_t(int ad, int *col, int *row); +typedef int vi_set_hw_cursor_t(int ad, int col, int row); +typedef int vi_diag_t(int level); + +struct vidsw { + vi_init_t *init; /* all */ + vi_adapter_t *adapter; /* all */ + vi_get_info_t *get_info; /* all */ + vi_query_mode_t *query_mode; /* all */ + vi_set_mode_t *set_mode; /* EGA/VGA */ + vi_save_font_t *save_font; /* EGA/VGA */ + vi_load_font_t *load_font; /* EGA/VGA */ + vi_show_font_t *show_font; /* EGA/VGA */ + vi_save_palette_t *save_palette; /* VGA */ + vi_load_palette_t *load_palette; /* VGA */ + vi_set_border_t *set_border; /* CGA/EGA/VGA */ + vi_save_state_t *save_state; /* VGA */ + vi_load_state_t *load_state; /* EGA/VGA */ + vi_set_win_org_t *set_win_org; /* all */ + vi_read_hw_cursor_t *read_hw_cursor; /* all */ + vi_set_hw_cursor_t *set_hw_cursor; /* all */ + vi_diag_t *diag; /* all */ +}; + +extern struct vidsw biosvidsw; + +#endif /* KERNEL */ + +#endif /* !_I386_ISA_VIDEOIO_H_ */ |