syscons.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,498 行 · 第 1/5 页
C
2,498 行
/*- * Copyright (c) 1992-1998 S鴕en 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, * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: syscons.c,v 1.293.2.3 1999/05/09 11:02:19 yokota Exp $ */#include "sc.h"#include "splash.h"#ifdef __i386__#include "apm.h"#endif#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#include <sys/param.h>#include <sys/systm.h>#include <sys/reboot.h>#include <sys/conf.h>#include <sys/proc.h>#include <sys/signalvar.h>#include <sys/tty.h>#include <sys/kernel.h>#include <sys/malloc.h>#ifdef DEVFS#include <sys/devfsext.h>#endif#include <machine/bootinfo.h>#include <machine/clock.h>#include <machine/cons.h>#include <machine/console.h>#include <machine/mouse.h>#include <machine/md_var.h>#include <machine/psl.h>#include <machine/frame.h>#include <machine/pc/display.h>#ifdef __i386__#include <machine/pc/vesa.h>#include <machine/apm_bios.h>#include <machine/random.h>#endif#include <vm/vm.h>#include <vm/vm_param.h>#include <vm/pmap.h>#include <dev/kbd/kbdreg.h>#include <dev/fb/fbreg.h>#include <dev/fb/vgareg.h>#include <dev/fb/splashreg.h>#include <dev/syscons/syscons.h>#ifndef __i386__#include <isa/isareg.h>#else#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>#include <i386/isa/timerreg.h>#endif#if !defined(MAXCONS)#define MAXCONS 16#endif#if !defined(SC_MAX_HISTORY_SIZE)#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)#endif#if !defined(SC_HISTORY_SIZE)#define SC_HISTORY_SIZE (ROW * 4)#endif#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE#undef SC_MAX_HISTORY_SIZE#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)#endif#if !defined(SC_MOUSE_CHAR)#define SC_MOUSE_CHAR (0xd0)#endif#define COLD 0#define WARM 1#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? *//* for backward compatibility */#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t)typedef struct old_mouse_data { int x; int y; int buttons;} old_mouse_data_t;typedef struct old_mouse_info { int operation; union { struct old_mouse_data data; struct mouse_mode mode; } u;} old_mouse_info_t;static default_attr user_default = { (FG_LIGHTGREY | BG_BLACK) << 8, (FG_BLACK | BG_LIGHTGREY) << 8};static default_attr kernel_default = { (FG_WHITE | BG_BLACK) << 8, (FG_BLACK | BG_LIGHTGREY) << 8};static scr_stat main_console;static scr_stat *console[MAXCONS];#ifdef DEVFSstatic void *sc_devfs_token[MAXCONS];static void *sc_mouse_devfs_token;static void *sc_console_devfs_token;#endif scr_stat *cur_console;static scr_stat *new_scp, *old_scp;static term_stat kernel_console;static default_attr *current_default;static int sc_flags;static char init_done = COLD;static u_short sc_buffer[ROW*COL];static char shutdown_in_progress = FALSE;static char font_loading_in_progress = FALSE;static char switch_in_progress = FALSE;static char write_in_progress = FALSE;static char blink_in_progress = FALSE;static int blinkrate = 0;static int adapter = -1;static int keyboard = -1;static keyboard_t *kbd;static int delayed_next_scr = FALSE;static long scrn_blank_time = 0; /* screen saver timeout value */static int scrn_blanked = FALSE; /* screen saver active flag */static long scrn_time_stamp;static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */static int run_scrn_saver = FALSE; /* should run the saver? */static int scrn_idle = FALSE; /* about to run the saver */#if NSPLASH > 0static int scrn_saver_failed;#endif u_char scr_map[256]; u_char scr_rmap[256];static int initial_video_mode; /* initial video mode # */ int fonts_loaded = 0#ifdef STD8X16FONT | FONT_16#endif ; u_char font_8[256*8]; u_char font_14[256*14];#ifdef STD8X16FONTextern#endif u_char font_16[256*16]; u_char palette[256*3];static u_char *cut_buffer;static int cut_buffer_size;static int mouse_level; /* sysmouse protocol level */static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 };static u_short mouse_and_mask[16] = { 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000 };static u_short mouse_or_mask[16] = { 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800, 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 }; 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; d_ioctl_t *sc_user_ioctl;static int sticky_splash = FALSE;static struct { u_int8_t cursor_start; u_int8_t cursor_end; u_int8_t shift_state; } bios_value;/* OS specific stuff */#ifdef not_yet_done#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x]))struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS]))struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1]))struct tty *sccons[MAXCONS+2];#else#define VIRTUAL_TTY(x) &sccons[x]#define CONSOLE_TTY &sccons[MAXCONS]#define MOUSE_TTY &sccons[MAXCONS+1]static struct tty sccons[MAXCONS+2];#endif#define SC_MOUSE 128#define SC_CONSOLE 255vm_offset_t Crtat;static const int nsccons = MAXCONS+2;#define WRAPHIST(scp, pointer, offset)\ ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ + (offset)) % (scp)->history_size))#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)/* some useful macros */#define kbd_read_char(kbd, wait) \ (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait))#define kbd_check_char(kbd) \ (*kbdsw[(kbd)->kb_index]->check_char)((kbd))#define kbd_enable(kbd) \ (*kbdsw[(kbd)->kb_index]->enable)((kbd))#define kbd_disable(kbd) \ (*kbdsw[(kbd)->kb_index]->disable)((kbd))#define kbd_lock(kbd, lockf) \ (*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf))#define kbd_ioctl(kbd, cmd, arg) \ (((kbd) == NULL) ? \ ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg)))#define kbd_clear_state(kbd) \ (*kbdsw[(kbd)->kb_index]->clear_state)((kbd))#define kbd_get_fkeystr(kbd, fkey, len) \ (*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len))#define kbd_poll(kbd, on) \ (*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))/* prototypes */static kbd_callback_func_t sckbdevent;static int scparam(struct tty *tp, struct termios *t);static int scvidprobe(int unit, int flags, int cons);static int sckbdprobe(int unit, int flags, int cons);static void scstart(struct tty *tp);static void scmousestart(struct tty *tp);static void scinit(void);static void scshutdown(int howto, void *arg);static u_int scgetc(keyboard_t *kbd, u_int flags);#define SCGETC_CN 1#define SCGETC_NONBLOCK 2static int sccngetch(int flags);static void sccnupdate(scr_stat *scp);static scr_stat *alloc_scp(void);static void init_scp(scr_stat *scp);static void get_bios_values(void);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);#if NSPLASH > 0static int scsplash_callback(int);static void scsplash_saver(int show);static int add_scrn_saver(void (*this_saver)(int));static int remove_scrn_saver(void (*this_saver)(int));static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border);static int restore_scrn_saver_mode(scr_stat *scp, int changemode);static void stop_scrn_saver(void (*saver)(int));static int wait_scrn_saver_stop(void);#define scsplash_stick(stick) (sticky_splash = (stick))#else /* !NSPLASH */#define stop_scrn_saver(saver)#define wait_scrn_saver_stop() 0#define scsplash_stick(stick)#endif /* NSPLASH */static int switch_scr(scr_stat *scp, u_int next_scr);static void exchange_scr(void);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 move_crsr(scr_stat *scp, int x, int y);static void history_to_screen(scr_stat *scp);static int history_up_line(scr_stat *scp);static int history_down_line(scr_stat *scp);static int mask2attr(struct term_stat *term);static int save_kbd_state(scr_stat *scp);static int update_kbd_state(int state, int mask);static int update_kbd_leds(int which);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);static int skip_spc_left(scr_stat *scp, u_short *p);static void mouse_cut(scr_stat *scp);static void mouse_cut_start(scr_stat *scp);static void mouse_cut_end(scr_stat *scp);static void mouse_cut_word(scr_stat *scp);static void mouse_cut_line(scr_stat *scp);static void mouse_cut_extend(scr_stat *scp);static void mouse_paste(scr_stat *scp);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 do_bell(scr_stat *scp, int pitch, int duration);static timeout_t blink_screen;#define CDEV_MAJOR 12#ifdef __i386__static cn_probe_t sccnprobe;static cn_init_t sccninit;static cn_getc_t sccngetc;static cn_checkc_t sccncheckc;static cn_putc_t sccnputc;CONS_DRIVER(sc, sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc);#else /* !__i386__ */static cn_getc_t sccngetc;static cn_checkc_t sccncheckc;static cn_putc_t sccnputc;struct consdev sc_cons = { NULL, NULL, sccngetc, sccncheckc, sccnputc, NULL, makedev(CDEV_MAJOR, 0), CN_NORMAL,};#endif /* __i386__ */static d_open_t scopen;static d_close_t scclose;static d_read_t scread;static d_write_t scwrite;static d_ioctl_t scioctl;static d_mmap_t scmmap;struct cdevsw sc_cdevsw = { scopen, scclose, scread, scwrite, scioctl, nullstop, noreset, scdevtotty, ttpoll, scmmap, nostrategy, "sc", NULL, -1, nodump, nopsize, D_TTY,};#ifdef __i386__#define fillw_io(p, b, c) fillw((p), (void *)(b), (c))#endif#ifdef __alpha__static voidfillw(int pat, void *base, size_t cnt){ u_short *sp = base; while (cnt--) *sp++ = pat;}static voidfillw_io(int pat, u_int32_t base, size_t cnt){ while (cnt--) { writew(base, pat); base += 2; }}#endifstatic voiddraw_cursor_image(scr_stat *scp){ u_short cursor_image; vm_offset_t ptr; u_short prev_image; if (ISPIXELSC(scp)) { sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, scp->cursor_pos - scp->scr_buf, 1); return; } ptr = scp->adp->va_window + 2*(scp->cursor_pos - scp->scr_buf); /* do we have a destructive cursor ? */ if (sc_flags & CHAR_CURSOR) { prev_image = scp->cursor_saveunder; cursor_image = readw(ptr) & 0x00ff; if (cursor_image == DEAD_CHAR) cursor_image = prev_image & 0x00ff; cursor_image |= *(scp->cursor_pos) & 0xff00; scp->cursor_saveunder = cursor_image; /* update the cursor bitmap if the char under the cursor has changed */ if (prev_image != cursor_image) set_destructive_cursor(scp); /* modify cursor_image */ if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ /* * When the mouse pointer is at the same position as the cursor, * the cursor bitmap needs to be updated even if the char under * the cursor hasn't changed, because the mouse pionter may * have moved by a few dots within the cursor cel. */ if ((prev_image == cursor_image) && (cursor_image != *(scp->cursor_pos))) set_destructive_cursor(scp); cursor_image &= 0xff00; cursor_image |= DEAD_CHAR; } } else { cursor_image = (readw(ptr) & 0x00ff) | (*(scp->cursor_pos) & 0xff00); scp->cursor_saveunder = cursor_image; if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ if ((cursor_image & 0x7000) == 0x7000) { cursor_image &= 0x8fff; if(!(cursor_image & 0x0700)) cursor_image |= 0x0700; } else { cursor_image |= 0x7000; if ((cursor_image & 0x0700) == 0x0700) cursor_image &= 0xf0ff; } } } writew(ptr, cursor_image);}static voidremove_cursor_image(scr_stat *scp){ if (ISPIXELSC(scp)) sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 0); else writew(scp->adp->va_window + 2*(scp->cursor_oldpos - scp->scr_buf), scp->cursor_saveunder);}static voidmove_crsr(scr_stat *scp, int x, int y){ if (x < 0) x = 0; if (y < 0) y = 0; if (x >= scp->xsize) x = scp->xsize-1; if (y >= scp->ysize) y = scp->ysize-1; scp->xpos = x; scp->ypos = y; scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos;}intsc_probe_unit(int unit, int flags){ if (!scvidprobe(unit, flags, FALSE)) { if (bootverbose) printf("sc%d: no video adapter is found.\n", unit); return ENXIO; } return ((sckbdprobe(unit, flags, FALSE)) ? 0 : ENXIO);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?