syscons.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,455 行 · 第 1/5 页
C
2,455 行
/*- * Copyright (c) 1992-1995 Sxren 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. * 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 * * 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.117.4.16 1997/02/05 05:41:50 davidg Exp $ */#include "sc.h"#include "apm.h"#if NSC > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/conf.h>#include <sys/ioctl.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/tty.h>#include <sys/uio.h>#include <sys/callout.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <sys/errno.h>#include <sys/malloc.h>#include <sys/devconf.h>#include <machine/clock.h>#include <machine/console.h>#include <machine/psl.h>#include <machine/frame.h>#include <machine/pc/display.h>#include <machine/apm_bios.h>#include <machine/random.h>#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>#include <i386/isa/timerreg.h>#include <i386/isa/kbdtables.h>#include <i386/i386/cons.h>#include <i386/isa/syscons.h>#if !defined(MAXCONS)#define MAXCONS 16#endif/* this may break on older VGA's but is usefull on real 32 bit systems */#define bcopyw bcopystatic 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]; scr_stat *cur_console;static scr_stat *new_scp, *old_scp;static term_stat kernel_console;static default_attr *current_default;static char init_done = FALSE;static int configuration = 0;static char switch_in_progress = FALSE;static char blink_in_progress = FALSE;static char write_in_progress = FALSE; u_int crtc_addr = MONO_BASE;static char crtc_vga = FALSE;static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;static char *font_8 = NULL, *font_14 = NULL, *font_16 = NULL;static int fonts_loaded = 0; char palette[3*256];static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);static int delayed_next_scr = FALSE;static long scrn_blank_time = 0; /* screen saver timeout value */ int scrn_blanked = FALSE; /* screen saver active flag */static int scrn_saver = 0; /* screen saver routine */static long scrn_time_stamp; u_char scr_map[256];static char *video_mode_ptr = NULL;#if ASYNCHstatic u_char kbd_reply = 0;#endifstatic 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};void none_saver(int blank) { }void (*current_saver)() = none_saver;/* 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 tty *sccons[MAXCONS+1];#else#define VIRTUAL_TTY(x) &sccons[x]#define CONSOLE_TTY &sccons[MAXCONS]struct tty sccons[MAXCONS+1];int nsccons = MAXCONS+1;#endif#define MONO_BUF pa_to_va(0xB0000)#define CGA_BUF pa_to_va(0xB8000)u_short *Crtat = (u_short *)MONO_BUF;#define WRAPHIST(scp, pointer, offset)\ ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\ + (offset)) % (scp->history_size)))struct isa_driver scdriver = { scprobe, scattach, "sc", 1};intscprobe(struct isa_device *dev){ int i, j, retries = 5; unsigned char val; int xt_keyboard = 0; /* Enable interrupts and keyboard controller */ kbd_wait(); outb(KB_STAT, KB_WRITE); kbd_wait(); outb(KB_DATA, KB_MODE); /* flush any noise in the buffer */ while (inb(KB_STAT) & KB_BUF_FULL) { DELAY(10); (void) inb(KB_DATA); } /* Reset keyboard hardware */ while (retries--) { kbd_wait(); outb(KB_DATA, KB_RESET); for (i=0; i<100000; i++) { DELAY(10); val = inb(KB_DATA); if (val == KB_ACK || val == KB_ECHO) goto gotres; if (val == KB_RESEND) break; } }gotres: if (retries < 0) printf("scprobe: keyboard won't accept RESET command\n"); else { i = 10; /* At most 10 retries. */gotack: DELAY(100); j = 1000; /* Wait at most 1 s. */ while ((inb(KB_STAT) & KB_BUF_FULL) == 0 && --j > 0) DELAY(1000); DELAY(1000); val = inb(KB_DATA); if (val == KB_ACK && --i > 0) goto gotack; if (val != KB_RESET_DONE) printf("scprobe: keyboard RESET failed (result = 0x%02x)\n", val); } /* * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards * such as those on the IBM ThinkPad laptop computers can be used * with the standard console driver. */ if ( dev->id_flags & XT_KEYBD ) xt_keyboard = 1;#ifdef XT_KEYBOARD xt_keyboard = 1;#endif if ( xt_keyboard ) { kbd_wait(); outb(KB_DATA, 0xF0); kbd_wait(); outb(KB_DATA, 1); kbd_wait(); } return (IO_KBDSIZE);}static struct kern_devconf kdc_sc[NSC] = { 0, 0, 0, /* filled in by dev_attach */ "sc", 0, { MDDT_ISA, 0, "tty" }, isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, &kdc_isa0, /* parent */ 0, /* parentdata */ DC_BUSY, /* the console is almost always busy */ "Graphics console", DC_CLS_DISPLAY /* class */};static inline voidsc_registerdev(struct isa_device *id){ if(id->id_unit) kdc_sc[id->id_unit] = kdc_sc[0]; kdc_sc[id->id_unit].kdc_unit = id->id_unit; kdc_sc[id->id_unit].kdc_isa = id; dev_attach(&kdc_sc[id->id_unit]);}#if NAPM > 0static intscresume(void *dummy){ shfts = 0; ctls = 0; alts = 0; agrs = 0; metas = 0; return 0;}#endifintscattach(struct isa_device *dev){ scr_stat *scp; scinit(); configuration = dev->id_flags; scp = console[0]; if (crtc_vga) { font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT); font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT); font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT); copy_font(SAVE, FONT_16, font_16); fonts_loaded = FONT_16; scp->font = FONT_16; save_palette(); } scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_NOWAIT); /* copy screen to buffer */ bcopyw(Crtat, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); scp->cursor_pos = scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; scp->mouse_pos = scp->scr_buf; /* initialize history buffer & pointers */ scp->history_head = scp->history_pos = scp->history = (u_short *)malloc(scp->history_size*sizeof(u_short), M_DEVBUF, M_NOWAIT); bzero(scp->history_head, scp->history_size*sizeof(u_short)); /* initialize cursor stuff */ draw_cursor(scp, TRUE); if (crtc_vga && (configuration & CHAR_CURSOR)) set_destructive_cursor(scp, TRUE); /* get screen update going */ scrn_timer(); update_leds(scp->status); sc_registerdev(dev); printf("sc%d: ", dev->id_unit); if (crtc_vga) if (crtc_addr == MONO_BASE) printf("VGA mono"); else printf("VGA color"); else if (crtc_addr == MONO_BASE) printf("MDA/hercules"); else printf("CGA/EGA"); printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, configuration);#if NAPM > 0 scp->r_hook.ah_fun = scresume; scp->r_hook.ah_arg = NULL; scp->r_hook.ah_name = "system keyboard"; scp->r_hook.ah_order = APM_MID_ORDER; apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook);#endif return 0;}struct tty*scdevtotty(dev_t dev){ int unit = minor(dev); if (!init_done) return(NULL); if (unit > MAXCONS || unit < 0) return(NULL); if (unit == MAXCONS) return CONSOLE_TTY; return VIRTUAL_TTY(unit);}static scr_stat*get_scr_stat(dev_t dev){ int unit = minor(dev); if (unit > MAXCONS || unit < 0) return(NULL); if (unit == MAXCONS) return console[0]; return console[unit];}static intget_scr_num(){ int i = 0; while ((i < MAXCONS) && (cur_console != console[i])) i++; return i < MAXCONS ? i : 0;}intscopen(dev_t dev, int flag, int mode, struct proc *p){ struct tty *tp = scdevtotty(dev); if (!tp) return(ENXIO); tp->t_oproc = scstart; tp->t_param = scparam; tp->t_dev = dev; if (!(tp->t_state & TS_ISOPEN)) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; scparam(tp, &tp->t_termios); ttsetwater(tp); (*linesw[tp->t_line].l_modem)(tp, 1); } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) return(EBUSY); if (!console[minor(dev)]) console[minor(dev)] = alloc_scp(); return((*linesw[tp->t_line].l_open)(dev, tp));}intscclose(dev_t dev, int flag, int mode, struct proc *p){ struct tty *tp = scdevtotty(dev); struct scr_stat *scp; if (!tp) return(ENXIO); if (minor(dev) < MAXCONS) { scp = get_scr_stat(tp->t_dev); if (scp->status & SWITCH_WAIT_ACQ) wakeup((caddr_t)&scp->smode);#if not_yet_done if (scp == &main_console) { scp->pid = 0; scp->proc = NULL; scp->smode.mode = VT_AUTO; } else { free(scp->scr_buf, M_DEVBUF); free(scp->history, M_DEVBUF); free(scp, M_DEVBUF); console[minor(dev)] = NULL; }#else scp->pid = 0; scp->proc = NULL; scp->smode.mode = VT_AUTO;#endif } spltty(); (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); spl0(); return(0);}intscread(dev_t dev, struct uio *uio, int flag){ struct tty *tp = scdevtotty(dev); if (!tp) return(ENXIO); return((*linesw[tp->t_line].l_read)(tp, uio, flag));}intscwrite(dev_t dev, struct uio *uio, int flag){ struct tty *tp = scdevtotty(dev); if (!tp) return(ENXIO); return((*linesw[tp->t_line].l_write)(tp, uio, flag));}voidscintr(int unit){ static struct tty *cur_tty; int c, len; u_char *cp; /* make screensaver happy */ scrn_time_stamp = time.tv_sec; if (scrn_blanked) { (*current_saver)(FALSE); cur_console->start = 0; cur_console->end = cur_console->xsize * cur_console->ysize; } c = scgetc(1); cur_tty = VIRTUAL_TTY(get_scr_num()); if (!(cur_tty->t_state & TS_ISOPEN)) if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) return; switch (c & 0xff00) { case 0x0000: /* normal key */ (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); break; case NOKEY: /* nothing there */ break; case FKEY: /* function key, return string */ if (cp = get_fstr((u_int)c, (u_int *)&len)) { while (len-- > 0) (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); } break; case MKEY: /* meta is active, prepend ESC */ (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); break; case BKEY: /* backtab fixed sequence (esc [ Z) */ (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); break; }}intscparam(struct tty *tp, struct termios *t){ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; tp->t_cflag = t->c_cflag; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?