syscons.c revision 42373
1262182Semaste/*- 2262182Semaste * Copyright (c) 1992-1998 S�ren Schmidt 3353358Sdim * All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6262182Semaste * modification, are permitted provided that the following conditions 7262182Semaste * are met: 8262182Semaste * 1. Redistributions of source code must retain the above copyright 9280031Sdim * notice, this list of conditions and the following disclaimer, 10280031Sdim * without modification, immediately at the beginning of the file. 11280031Sdim * 2. Redistributions in binary form must reproduce the above copyright 12262182Semaste * notice, this list of conditions and the following disclaimer in the 13314564Sdim * documentation and/or other materials provided with the distribution. 14314564Sdim * 3. The name of the author may not be used to endorse or promote products 15344779Sdim * derived from this software without specific prior written permission. 16262182Semaste * 17360784Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18321369Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19288943Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20314564Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21321369Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22321369Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23321369Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24321369Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25262182Semaste * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26321369Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27321369Sdim * 28321369Sdim * $Id: syscons.c,v 1.288 1998/12/07 21:58:23 archie Exp $ 29262182Semaste */ 30280031Sdim 31262182Semaste#include "sc.h" 32288943Sdim#include "apm.h" 33288943Sdim#include "opt_ddb.h" 34288943Sdim#include "opt_devfs.h" 35288943Sdim#include "opt_vesa.h" 36288943Sdim#include "opt_vm86.h" 37341825Sdim#include "opt_syscons.h" 38341825Sdim 39288943Sdim#if NSC > 0 40288943Sdim#include <sys/param.h> 41314564Sdim#include <sys/systm.h> 42288943Sdim#include <sys/reboot.h> 43288943Sdim#include <sys/conf.h> 44288943Sdim#include <sys/proc.h> 45288943Sdim#include <sys/signalvar.h> 46314564Sdim#include <sys/tty.h> 47341825Sdim#include <sys/kernel.h> 48341825Sdim#include <sys/malloc.h> 49341825Sdim#ifdef DEVFS 50341825Sdim#include <sys/devfsext.h> 51280031Sdim#endif 52280031Sdim 53280031Sdim#include <machine/bootinfo.h> 54280031Sdim#include <machine/clock.h> 55280031Sdim#include <machine/cons.h> 56280031Sdim#include <machine/console.h> 57280031Sdim#include <machine/mouse.h> 58280031Sdim#include <machine/md_var.h> 59280031Sdim#include <machine/psl.h> 60280031Sdim#include <machine/frame.h> 61280031Sdim#include <machine/pc/display.h> 62280031Sdim#include <machine/pc/vesa.h> 63280031Sdim#include <machine/apm_bios.h> 64280031Sdim#include <machine/random.h> 65280031Sdim 66280031Sdim#include <vm/vm.h> 67280031Sdim#include <vm/vm_param.h> 68280031Sdim#include <vm/pmap.h> 69280031Sdim 70280031Sdim#include <i386/isa/isa.h> 71314564Sdim#include <i386/isa/isa_device.h> 72341825Sdim#include <i386/isa/timerreg.h> 73280031Sdim#include <i386/isa/kbdtables.h> 74280031Sdim#include <i386/isa/kbdio.h> 75280031Sdim#include <i386/isa/videoio.h> 76280031Sdim#include <i386/isa/syscons.h> 77280031Sdim 78280031Sdim#if !defined(MAXCONS) 79280031Sdim#define MAXCONS 16 80280031Sdim#endif 81280031Sdim 82280031Sdim#if !defined(SC_MAX_HISTORY_SIZE) 83280031Sdim#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS) 84314564Sdim#endif 85314564Sdim 86280031Sdim#if !defined(SC_HISTORY_SIZE) 87280031Sdim#define SC_HISTORY_SIZE (ROW * 4) 88314564Sdim#endif 89280031Sdim 90280031Sdim#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE 91280031Sdim#undef SC_MAX_HISTORY_SIZE 92314564Sdim#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS) 93314564Sdim#endif 94314564Sdim 95314564Sdim#if !defined(SC_MOUSE_CHAR) 96314564Sdim#define SC_MOUSE_CHAR (0xd0) 97314564Sdim#endif 98280031Sdim 99280031Sdim#define COLD 0 100360784Sdim#define WARM 1 101360784Sdim 102360784Sdim#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ 103360784Sdim#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ 104360784Sdim 105360784Sdim/* for backward compatibility */ 106360784Sdim#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 107360784Sdim 108360784Sdimtypedef struct old_mouse_data { 109360784Sdim int x; 110360784Sdim int y; 111360784Sdim int buttons; 112360784Sdim} old_mouse_data_t; 113360784Sdim 114360784Sdimtypedef struct old_mouse_info { 115360784Sdim int operation; 116360784Sdim union { 117360784Sdim struct old_mouse_data data; 118360784Sdim struct mouse_mode mode; 119360784Sdim } u; 120360784Sdim} old_mouse_info_t; 121360784Sdim 122360784Sdim/* XXX use sc_bcopy where video memory is concerned */ 123360784Sdimextern void generic_bcopy(const void *, void *, size_t); 124360784Sdimextern void generic_bzero(void *, size_t); 125360784Sdim 126360784Sdimstatic default_attr user_default = { 127314564Sdim (FG_LIGHTGREY | BG_BLACK) << 8, 128314564Sdim (FG_BLACK | BG_LIGHTGREY) << 8 129314564Sdim}; 130314564Sdim 131314564Sdimstatic default_attr kernel_default = { 132314564Sdim (FG_WHITE | BG_BLACK) << 8, 133280031Sdim (FG_BLACK | BG_LIGHTGREY) << 8 134280031Sdim}; 135314564Sdim 136314564Sdimstatic scr_stat main_console; 137314564Sdimstatic scr_stat *console[MAXCONS]; 138314564Sdim#ifdef DEVFS 139314564Sdimstatic void *sc_devfs_token[MAXCONS]; 140314564Sdimstatic void *sc_mouse_devfs_token; 141314564Sdimstatic void *sc_console_devfs_token; 142314564Sdim#endif 143280031Sdim scr_stat *cur_console; 144314564Sdimstatic scr_stat *new_scp, *old_scp; 145314564Sdimstatic term_stat kernel_console; 146314564Sdimstatic default_attr *current_default; 147314564Sdimstatic int sc_flags; 148280031Sdimstatic int sc_port = IO_KBD; 149280031Sdimstatic KBDC sc_kbdc = NULL; 150314564Sdimstatic char init_done = COLD; 151314564Sdimstatic u_short sc_buffer[ROW*COL]; 152314564Sdimstatic char shutdown_in_progress = FALSE; 153314564Sdimstatic char font_loading_in_progress = FALSE; 154314564Sdimstatic char switch_in_progress = FALSE; 155314564Sdimstatic char write_in_progress = FALSE; 156314564Sdimstatic char blink_in_progress = FALSE; 157280031Sdimstatic int blinkrate = 0; 158280031Sdim u_int crtc_addr = MONO_BASE; 159314564Sdim char crtc_type = KD_MONO; 160314564Sdimstatic char crtc_vga = FALSE; 161314564Sdimstatic int adp_flags; 162314564Sdimstatic u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 163314564Sdimstatic u_char accents = 0; 164314564Sdimstatic u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 165314564Sdimstatic const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 166314564Sdimstatic int delayed_next_scr = FALSE; 167280031Sdimstatic long scrn_blank_time = 0; /* screen saver timeout value */ 168280031Sdim int scrn_blanked = 0; /* screen saver active flag */ 169314564Sdimstatic long scrn_time_stamp; 170314564Sdimstatic int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */ 171314564Sdimstatic int run_scrn_saver = FALSE; /* should run the saver? */ 172314564Sdimstatic int scrn_idle = FALSE; /* about to run the saver */ 173341825Sdim u_char scr_map[256]; 174341825Sdim u_char scr_rmap[256]; 175314564Sdimstatic int initial_video_mode; /* initial video mode # */ 176314564Sdimstatic int bios_video_mode; /* video mode # set by BIOS */ 177314564Sdim int fonts_loaded = 0 178314564Sdim#ifdef STD8X16FONT 179314564Sdim | FONT_16 180280031Sdim#endif 181280031Sdim ; 182314564Sdim 183314564Sdim u_char font_8[256*8]; 184314564Sdim u_char font_14[256*14]; 185280031Sdim#ifdef STD8X16FONT 186341825Sdimextern 187341825Sdim#endif 188280031Sdim u_char font_16[256*16]; 189314564Sdim u_char palette[256*3]; 190314564Sdimstatic u_char *cut_buffer; 191341825Sdimstatic int cut_buffer_size; 192341825Sdimstatic int mouse_level; /* sysmouse protocol level */ 193314564Sdimstatic mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; 194353358Sdimstatic u_short mouse_and_mask[16] = { 195314564Sdim 0xc000, 0xe000, 0xf000, 0xf800, 196314564Sdim 0xfc00, 0xfe00, 0xff00, 0xff80, 197314564Sdim 0xfe00, 0x1e00, 0x1f00, 0x0f00, 198314564Sdim 0x0f00, 0x0000, 0x0000, 0x0000 199314564Sdim }; 200314564Sdimstatic u_short mouse_or_mask[16] = { 201314564Sdim 0x0000, 0x4000, 0x6000, 0x7000, 202353358Sdim 0x7800, 0x7c00, 0x7e00, 0x6800, 203314564Sdim 0x0c00, 0x0c00, 0x0600, 0x0600, 204353358Sdim 0x0000, 0x0000, 0x0000, 0x0000 205353358Sdim }; 206353358Sdim 207353358Sdim int sc_history_size = SC_HISTORY_SIZE; 208353358Sdimstatic int extra_history_size = 209353358Sdim SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; 210353358Sdim 211353358Sdimstatic void none_saver(int blank) { } 212353358Sdimstatic void (*current_saver)(int blank) = none_saver; 213353358Sdimstatic void (*default_saver)(int blank) = none_saver; 214353358Sdim d_ioctl_t *sc_user_ioctl; 215353358Sdim 216353358Sdimstatic int sticky_splash = FALSE; 217353358Sdim 218314564Sdim/* OS specific stuff */ 219280031Sdim#ifdef not_yet_done 220353358Sdim#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 221314564Sdimstruct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 222353358Sdimstruct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) 223353358Sdimstruct tty *sccons[MAXCONS+2]; 224314564Sdim#else 225314564Sdim#define VIRTUAL_TTY(x) &sccons[x] 226314564Sdim#define CONSOLE_TTY &sccons[MAXCONS] 227314564Sdim#define MOUSE_TTY &sccons[MAXCONS+1] 228314564Sdimstatic struct tty sccons[MAXCONS+2]; 229314564Sdim#endif 230314564Sdim#define SC_MOUSE 128 231314564Sdim#define SC_CONSOLE 255 232314564Sdimu_short *Crtat; 233353358Sdimstatic const int nsccons = MAXCONS+2; 234314564Sdim 235314564Sdim#define WRAPHIST(scp, pointer, offset)\ 236314564Sdim ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ 237314564Sdim + (offset)) % (scp)->history_size)) 238314564Sdim#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 239314564Sdim 240314564Sdim/* prototypes */ 241314564Sdimstatic int scattach(struct isa_device *dev); 242314564Sdimstatic ointhand2_t scintr; 243314564Sdimstatic int scparam(struct tty *tp, struct termios *t); 244314564Sdimstatic int scprobe(struct isa_device *dev); 245314564Sdimstatic int scvidprobe(int unit, int flags); 246314564Sdimstatic int sckbdprobe(int unit, int flags); 247314564Sdimstatic void scstart(struct tty *tp); 248314564Sdimstatic void scmousestart(struct tty *tp); 249314564Sdimstatic void scinit(void); 250314564Sdimstatic void scshutdown(int howto, void *arg); 251314564Sdimstatic u_int scgetc(u_int flags); 252314564Sdim#define SCGETC_CN 1 253314564Sdim#define SCGETC_NONBLOCK 2 254314564Sdimstatic void sccnupdate(scr_stat *scp); 255353358Sdimstatic scr_stat *alloc_scp(void); 256314564Sdimstatic void init_scp(scr_stat *scp); 257314564Sdimstatic void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); 258314564Sdimstatic int get_scr_num(void); 259314564Sdimstatic timeout_t scrn_timer; 260314564Sdimstatic void scrn_update(scr_stat *scp, int show_cursor); 261314564Sdimstatic void scrn_saver(void (*saver)(int), int blank); 262314564Sdimstatic void stop_scrn_saver(void (*saver)(int)); 263314564Sdimstatic int wait_scrn_saver_stop(void); 264314564Sdimstatic int switch_scr(scr_stat *scp, u_int next_scr); 265314564Sdimstatic void exchange_scr(void); 266314564Sdimstatic void scan_esc(scr_stat *scp, u_char c); 267314564Sdimstatic void ansi_put(scr_stat *scp, u_char *buf, int len); 268314564Sdimstatic void draw_cursor_image(scr_stat *scp); 269314564Sdimstatic void remove_cursor_image(scr_stat *scp); 270314564Sdimstatic void move_crsr(scr_stat *scp, int x, int y); 271314564Sdimstatic u_char *get_fstr(u_int c, u_int *len); 272314564Sdimstatic void history_to_screen(scr_stat *scp); 273314564Sdimstatic int history_up_line(scr_stat *scp); 274314564Sdimstatic int history_down_line(scr_stat *scp); 275314564Sdimstatic int mask2attr(struct term_stat *term); 276314564Sdimstatic void set_keyboard(int command, int data); 277314564Sdimstatic void update_leds(int which); 278314564Sdimstatic void set_destructive_cursor(scr_stat *scp); 279314564Sdimstatic void set_mouse_pos(scr_stat *scp); 280314564Sdimstatic int skip_spc_right(scr_stat *scp, u_short *p); 281314564Sdimstatic int skip_spc_left(scr_stat *scp, u_short *p); 282314564Sdimstatic void mouse_cut(scr_stat *scp); 283314564Sdimstatic void mouse_cut_start(scr_stat *scp); 284314564Sdimstatic void mouse_cut_end(scr_stat *scp); 285314564Sdimstatic void mouse_cut_word(scr_stat *scp); 286314564Sdimstatic void mouse_cut_line(scr_stat *scp); 287314564Sdimstatic void mouse_cut_extend(scr_stat *scp); 288314564Sdimstatic void mouse_paste(scr_stat *scp); 289314564Sdimstatic void draw_mouse_image(scr_stat *scp); 290314564Sdimstatic void remove_mouse_image(scr_stat *scp); 291314564Sdimstatic void draw_cutmarking(scr_stat *scp); 292314564Sdimstatic void remove_cutmarking(scr_stat *scp); 293276479Sdimstatic void do_bell(scr_stat *scp, int pitch, int duration); 294314564Sdimstatic timeout_t blink_screen; 295276479Sdim#ifdef SC_SPLASH_SCREEN 296280031Sdimstatic void scsplash_init(scr_stat *scp); 297276479Sdimstatic void scsplash_term(scr_stat *scp); 298314564Sdimstatic void scsplash_saver(int show); 299314564Sdim#define scsplash_stick(stick) (sticky_splash = (stick)) 300314564Sdim#else 301314564Sdim#define scsplash_stick(stick) 302314564Sdim#endif 303314564Sdim 304280031Sdimstatic cn_probe_t sccnprobe; 305262182Semastestatic cn_init_t sccninit; 306314564Sdimstatic cn_getc_t sccngetc; 307314564Sdimstatic cn_checkc_t sccncheckc; 308314564Sdimstatic cn_putc_t sccnputc; 309314564Sdim 310314564SdimCONS_DRIVER(sc, sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc); 311314564Sdim 312314564Sdimstruct isa_driver scdriver = { 313314564Sdim scprobe, scattach, "sc", 1 314314564Sdim}; 315314564Sdim 316314564Sdimstatic d_open_t scopen; 317314564Sdimstatic d_close_t scclose; 318314564Sdimstatic d_read_t scread; 319280031Sdimstatic d_write_t scwrite; 320314564Sdimstatic d_ioctl_t scioctl; 321314564Sdimstatic d_mmap_t scmmap; 322262182Semaste 323314564Sdim#define CDEV_MAJOR 12 324262182Semastestatic struct cdevsw sc_cdevsw = { 325314564Sdim scopen, scclose, scread, scwrite, 326314564Sdim scioctl, nullstop, noreset, scdevtotty, 327314564Sdim ttpoll, scmmap, nostrategy, "sc", 328314564Sdim NULL, -1, nodump, nopsize, 329314564Sdim D_TTY, 330314564Sdim}; 331314564Sdim 332314564Sdimstatic void 333280031Sdimdraw_cursor_image(scr_stat *scp) 334262182Semaste{ 335314564Sdim u_short cursor_image; 336314564Sdim u_short *ptr; 337314564Sdim u_short prev_image; 338280031Sdim 339262182Semaste if (ISPIXELSC(scp)) { 340314564Sdim sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 341280031Sdim scp->cursor_pos - scp->scr_buf, 1); 342314564Sdim return; 343314564Sdim } 344314564Sdim 345314564Sdim ptr = (u_short *)(get_adapter(scp)->va_window) 346280031Sdim + (scp->cursor_pos - scp->scr_buf); 347262182Semaste 348314564Sdim /* do we have a destructive cursor ? */ 349314564Sdim if (sc_flags & CHAR_CURSOR) { 350314564Sdim prev_image = scp->cursor_saveunder; 351314564Sdim cursor_image = *ptr & 0x00ff; 352314564Sdim if (cursor_image == DEAD_CHAR) 353314564Sdim cursor_image = prev_image & 0x00ff; 354314564Sdim cursor_image |= *(scp->cursor_pos) & 0xff00; 355314564Sdim scp->cursor_saveunder = cursor_image; 356280031Sdim /* update the cursor bitmap if the char under the cursor has changed */ 357280031Sdim if (prev_image != cursor_image) 358314564Sdim set_destructive_cursor(scp); 359314564Sdim /* modify cursor_image */ 360314564Sdim if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 361314564Sdim /* 362314564Sdim * When the mouse pointer is at the same position as the cursor, 363314564Sdim * the cursor bitmap needs to be updated even if the char under 364314564Sdim * the cursor hasn't changed, because the mouse pionter may 365276479Sdim * have moved by a few dots within the cursor cel. 366314564Sdim */ 367314564Sdim if ((prev_image == cursor_image) 368314564Sdim && (cursor_image != *(scp->cursor_pos))) 369314564Sdim set_destructive_cursor(scp); 370314564Sdim cursor_image &= 0xff00; 371314564Sdim cursor_image |= DEAD_CHAR; 372314564Sdim } 373314564Sdim } else { 374276479Sdim cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; 375314564Sdim scp->cursor_saveunder = cursor_image; 376314564Sdim if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 377262182Semaste if ((cursor_image & 0x7000) == 0x7000) { 378262182Semaste cursor_image &= 0x8fff; 379314564Sdim if(!(cursor_image & 0x0700)) 380314564Sdim cursor_image |= 0x0700; 381314564Sdim } else { 382314564Sdim cursor_image |= 0x7000; 383314564Sdim if ((cursor_image & 0x0700) == 0x0700) 384314564Sdim cursor_image &= 0xf0ff; 385314564Sdim } 386314564Sdim } 387314564Sdim } 388314564Sdim *ptr = cursor_image; 389314564Sdim} 390314564Sdim 391314564Sdimstatic void 392314564Sdimremove_cursor_image(scr_stat *scp) 393314564Sdim{ 394314564Sdim if (ISPIXELSC(scp)) 395314564Sdim sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 396314564Sdim scp->cursor_oldpos - scp->scr_buf, 0); 397314564Sdim else 398314564Sdim *((u_short *)(get_adapter(scp)->va_window) 399321369Sdim + (scp->cursor_oldpos - scp->scr_buf)) 400314564Sdim = scp->cursor_saveunder; 401314564Sdim} 402314564Sdim 403314564Sdimstatic void 404314564Sdimmove_crsr(scr_stat *scp, int x, int y) 405314564Sdim{ 406280031Sdim if (x < 0) 407262182Semaste x = 0; 408314564Sdim if (y < 0) 409314564Sdim y = 0; 410314564Sdim if (x >= scp->xsize) 411314564Sdim x = scp->xsize-1; 412314564Sdim if (y >= scp->ysize) 413280031Sdim y = scp->ysize-1; 414314564Sdim scp->xpos = x; 415314564Sdim scp->ypos = y; 416314564Sdim scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 417314564Sdim} 418314564Sdim 419314564Sdimstatic int 420314564Sdimscprobe(struct isa_device *dev) 421314564Sdim{ 422314564Sdim if (!scvidprobe(dev->id_unit, dev->id_flags)) { 423262182Semaste if (bootverbose) 424262182Semaste printf("sc%d: no video adapter is found.\n", dev->id_unit); 425314564Sdim return (0); 426314564Sdim } 427314564Sdim 428314564Sdim#if defined(VESA) && defined(VM86) 429314564Sdim if (vesa_load()) 430262182Semaste return FALSE; 431262182Semaste#endif 432314564Sdim 433314564Sdim (*biosvidsw.diag)(bootverbose); 434314564Sdim 435314564Sdim sc_port = dev->id_iobase; 436314564Sdim if (sckbdprobe(dev->id_unit, dev->id_flags)) 437314564Sdim return (IO_KBDSIZE); 438314564Sdim else 439314564Sdim return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); 440314564Sdim} 441314564Sdim 442314564Sdim/* probe video adapters, return TRUE if found */ 443280031Sdimstatic int 444314564Sdimscvidprobe(int unit, int flags) 445280031Sdim{ 446314564Sdim video_adapter_t *adp; 447280031Sdim 448314564Sdim /* do this test only once */ 449314564Sdim if (init_done != COLD) 450314564Sdim return (crtc_type != -1); 451262182Semaste 452262182Semaste if ((*biosvidsw.init)() <= 0) 453360784Sdim return FALSE; 454360784Sdim if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL) 455314564Sdim return FALSE; 456314564Sdim 457314564Sdim crtc_type = adp->va_type; 458314564Sdim crtc_vga = (crtc_type == KD_VGA); 459314564Sdim crtc_addr = adp->va_crtc_addr; 460314564Sdim Crtat = (u_short *)adp->va_window; 461314564Sdim adp_flags = adp->va_flags; 462314564Sdim initial_video_mode = adp->va_initial_mode; 463314564Sdim bios_video_mode = adp->va_initial_bios_mode; 464360784Sdim 465360784Sdim return TRUE; 466314564Sdim} 467360784Sdim 468360784Sdim/* probe the keyboard, return TRUE if found */ 469360784Sdimstatic int 470360784Sdimsckbdprobe(int unit, int flags) 471360784Sdim{ 472360784Sdim int codeset; 473360784Sdim int c = -1; 474360784Sdim int m; 475360784Sdim int res, id; 476360784Sdim 477360784Sdim sc_kbdc = kbdc_open(sc_port); 478360784Sdim 479360784Sdim if (!kbdc_lock(sc_kbdc, TRUE)) { 480360784Sdim /* driver error? */ 481360784Sdim printf("sc%d: unable to lock the controller.\n", unit); 482314564Sdim return ((flags & DETECT_KBD) ? FALSE : TRUE); 483360784Sdim } 484360784Sdim 485360784Sdim /* flush any noise in the buffer */ 486360784Sdim empty_both_buffers(sc_kbdc, 10); 487280031Sdim 488360784Sdim /* save the current keyboard controller command byte */ 489360784Sdim m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; 490360784Sdim c = get_controller_command_byte(sc_kbdc); 491360784Sdim if (c == -1) { 492360784Sdim /* CONTROLLER ERROR */ 493360784Sdim printf("sc%d: unable to get the current command byte value.\n", unit); 494360784Sdim goto fail; 495360784Sdim } 496280031Sdim if (bootverbose) 497314564Sdim printf("sc%d: the current keyboard controller command byte %04x\n", 498280031Sdim unit, c); 499314564Sdim#if 0 500314564Sdim /* override the keyboard lock switch */ 501314564Sdim c |= KBD_OVERRIDE_KBD_LOCK; 502280031Sdim#endif 503314564Sdim 504314564Sdim /* 505314564Sdim * The keyboard may have been screwed up by the boot block. 506314564Sdim * We may just be able to recover from error by testing the controller 507314564Sdim * and the keyboard port. The controller command byte needs to be saved 508314564Sdim * before this recovery operation, as some controllers seem to set 509341825Sdim * the command byte to particular values. 510360784Sdim */ 511360784Sdim test_controller(sc_kbdc); 512360784Sdim test_kbd_port(sc_kbdc); 513360784Sdim 514360784Sdim /* enable the keyboard port, but disable the keyboard intr. */ 515360784Sdim if (!set_controller_command_byte(sc_kbdc, 516360784Sdim KBD_KBD_CONTROL_BITS, 517360784Sdim KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { 518360784Sdim /* CONTROLLER ERROR 519360784Sdim * there is very little we can do... 520360784Sdim */ 521314564Sdim printf("sc%d: unable to set the command byte.\n", unit); 522314564Sdim goto fail; 523262182Semaste } 524262182Semaste 525321369Sdim /* 526314564Sdim * Check if we have an XT keyboard before we attempt to reset it. 527314564Sdim * The procedure assumes that the keyboard and the controller have 528314564Sdim * been set up properly by BIOS and have not been messed up 529314564Sdim * during the boot process. 530314564Sdim */ 531314564Sdim codeset = -1; 532314564Sdim if (flags & XT_KEYBD) 533314564Sdim /* the user says there is a XT keyboard */ 534314564Sdim codeset = 1; 535314564Sdim#ifdef DETECT_XT_KEYBOARD 536314564Sdim else if ((c & KBD_TRANSLATION) == 0) { 537314564Sdim /* SET_SCANCODE_SET is not always supported; ignore error */ 538314564Sdim if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) 539314564Sdim == KBD_ACK) 540314564Sdim codeset = read_kbd_data(sc_kbdc); 541341825Sdim } 542341825Sdim if (bootverbose) 543314564Sdim printf("sc%d: keyboard scancode set %d\n", unit, codeset); 544314564Sdim#endif /* DETECT_XT_KEYBOARD */ 545314564Sdim 546314564Sdim if (flags & KBD_NORESET) { 547314564Sdim write_kbd_command(sc_kbdc, KBDC_ECHO); 548314564Sdim if (read_kbd_data(sc_kbdc) != KBD_ECHO) { 549314564Sdim empty_both_buffers(sc_kbdc, 10); 550314564Sdim test_controller(sc_kbdc); 551262182Semaste test_kbd_port(sc_kbdc); 552314564Sdim if (bootverbose) 553314564Sdim printf("sc%d: failed to get response from the keyboard.\n", 554314564Sdim unit); 555314564Sdim goto fail; 556314564Sdim } 557314564Sdim } else { 558314564Sdim /* reset keyboard hardware */ 559314564Sdim if (!reset_kbd(sc_kbdc)) { 560314564Sdim /* KEYBOARD ERROR 561341825Sdim * Keyboard reset may fail either because the keyboard doen't 562341825Sdim * exist, or because the keyboard doesn't pass the self-test, 563341825Sdim * or the keyboard controller on the motherboard and the keyboard 564341825Sdim * somehow fail to shake hands. It is just possible, particularly 565314564Sdim * in the last case, that the keyoard controller may be left 566353358Sdim * in a hung state. test_controller() and test_kbd_port() appear 567353358Sdim * to bring the keyboard controller back (I don't know why and 568314564Sdim * how, though.) 569314564Sdim */ 570314564Sdim empty_both_buffers(sc_kbdc, 10); 571353358Sdim test_controller(sc_kbdc); 572353358Sdim test_kbd_port(sc_kbdc); 573314564Sdim /* We could disable the keyboard port and interrupt... but, 574314564Sdim * the keyboard may still exist (see above). 575280031Sdim */ 576288943Sdim if (bootverbose) 577314564Sdim printf("sc%d: failed to reset the keyboard.\n", unit); 578314564Sdim goto fail; 579314564Sdim } 580314564Sdim } 581314564Sdim 582314564Sdim /* 583314564Sdim * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards 584288943Sdim * such as those on the IBM ThinkPad laptop computers can be used 585314564Sdim * with the standard console driver. 586344779Sdim */ 587288943Sdim if (codeset == 1) { 588314564Sdim if (send_kbd_command_and_data( 589314564Sdim sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 590314564Sdim /* XT kbd doesn't need scan code translation */ 591314564Sdim c &= ~KBD_TRANSLATION; 592314564Sdim } else { 593314564Sdim /* KEYBOARD ERROR 594314564Sdim * The XT kbd isn't usable unless the proper scan code set 595314564Sdim * is selected. 596314564Sdim */ 597314564Sdim printf("sc%d: unable to set the XT keyboard mode.\n", unit); 598262182Semaste goto fail; 599314564Sdim } 600262182Semaste } 601262182Semaste /* enable the keyboard port and intr. */ 602314564Sdim if (!set_controller_command_byte(sc_kbdc, 603314564Sdim KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 604314564Sdim (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 605314564Sdim | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 606280031Sdim /* CONTROLLER ERROR 607262182Semaste * This is serious; we are left with the disabled keyboard intr. 608314564Sdim */ 609314564Sdim printf("sc%d: unable to enable the keyboard port and intr.\n", unit); 610314564Sdim goto fail; 611314564Sdim } 612314564Sdim 613314564Sdim /* Get the ID of the keyboard, if any */ 614314564Sdim empty_kbd_buffer(sc_kbdc, 5); 615314564Sdim res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID); 616262182Semaste if (res == KBD_ACK) { 617314564Sdim /* 10ms delay */ 618314564Sdim DELAY(10000); 619314564Sdim id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc); 620262182Semaste if (bootverbose) 621314564Sdim printf("sc%d: keyboard device ID: %04x\n", unit, id); 622314564Sdim } 623314564Sdim 624314564Sdim kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), 625314564Sdim kbdc_lock(sc_kbdc, FALSE); 626314564Sdim return TRUE; 627314564Sdim 628314564Sdimfail: 629314564Sdim if (c != -1) 630280031Sdim /* try to restore the command byte as before, if possible */ 631314564Sdim set_controller_command_byte(sc_kbdc, 0xff, c); 632280031Sdim kbdc_set_device_mask(sc_kbdc, 633314564Sdim (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); 634280031Sdim kbdc_lock(sc_kbdc, FALSE); 635314564Sdim return FALSE; 636314564Sdim} 637314564Sdim 638314564Sdim#if NAPM > 0 639314564Sdimstatic int 640262182Semastescresume(void *dummy) 641314564Sdim{ 642314564Sdim shfts = ctls = alts = agrs = metas = accents = 0; 643314564Sdim return 0; 644314564Sdim} 645314564Sdim#endif 646314564Sdim 647314564Sdimstatic int 648314564Sdimscattach(struct isa_device *dev) 649314564Sdim{ 650314564Sdim scr_stat *scp; 651314564Sdim#if defined(VESA) && defined(VM86) 652314564Sdim video_info_t info; 653280031Sdim#endif 654262182Semaste dev_t cdev = makedev(CDEV_MAJOR, 0); 655314564Sdim#ifdef DEVFS 656314564Sdim int vc; 657314564Sdim#endif 658314564Sdim 659314564Sdim dev->id_ointr = scintr; 660314564Sdim scinit(); 661309124Sdim sc_flags = dev->id_flags; 662314564Sdim if (!ISFONTAVAIL(adp_flags)) 663314564Sdim sc_flags &= ~CHAR_CURSOR; 664309124Sdim 665341825Sdim scp = console[0]; 666341825Sdim 667314564Sdim /* copy temporary buffer to final buffer */ 668314564Sdim scp->scr_buf = NULL; 669314564Sdim sc_alloc_scr_buffer(scp, FALSE, FALSE); 670314564Sdim bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short)); 671314564Sdim 672314564Sdim /* cut buffer is available only when the mouse pointer is used */ 673314564Sdim if (ISMOUSEAVAIL(adp_flags)) 674314564Sdim sc_alloc_cut_buffer(scp, FALSE); 675314564Sdim 676309124Sdim /* initialize history buffer & pointers */ 677314564Sdim sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); 678314564Sdim 679314564Sdim#if defined(VESA) && defined(VM86) 680309124Sdim if ((sc_flags & VESA800X600) 681314564Sdim && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { 682314564Sdim#ifdef SC_SPLASH_SCREEN 683309124Sdim scsplash_term(scp); 684314564Sdim#endif 685309124Sdim sc_set_graphics_mode(scp, NULL, M_VESA_800x600); 686314564Sdim sc_set_pixel_mode(scp, NULL, COL, ROW, 16); 687309124Sdim initial_video_mode = M_VESA_800x600; 688314564Sdim#ifdef SC_SPLASH_SCREEN 689314564Sdim scsplash_init(scp); 690314564Sdim#endif 691314564Sdim } 692314564Sdim#endif /* VESA && VM86 */ 693309124Sdim 694309124Sdim /* initialize cursor stuff */ 695314564Sdim if (!ISGRAPHSC(scp)) 696314564Sdim draw_cursor_image(scp); 697276479Sdim 698314564Sdim /* get screen update going */ 699314564Sdim scrn_timer((void *)TRUE); 700314564Sdim 701314564Sdim update_leds(scp->status); 702280031Sdim 703314564Sdim printf("sc%d: ", dev->id_unit); 704262182Semaste switch(crtc_type) { 705341825Sdim case KD_VGA: 706341825Sdim printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); 707314564Sdim break; 708314564Sdim case KD_EGA: 709314564Sdim printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); 710314564Sdim break; 711314564Sdim case KD_CGA: 712262182Semaste printf("CGA"); 713314564Sdim break; 714314564Sdim case KD_MONO: 715314564Sdim case KD_HERCULES: 716314564Sdim default: 717314564Sdim printf("MDA/Hercules"); 718314564Sdim break; 719314564Sdim } 720314564Sdim printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, sc_flags); 721314564Sdim 722314564Sdim#if NAPM > 0 723314564Sdim scp->r_hook.ah_fun = scresume; 724314564Sdim scp->r_hook.ah_arg = NULL; 725314564Sdim scp->r_hook.ah_name = "system keyboard"; 726314564Sdim scp->r_hook.ah_order = APM_MID_ORDER; 727314564Sdim apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 728314564Sdim#endif 729314564Sdim 730314564Sdim at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC); 731314564Sdim 732262182Semaste cdevsw_add(&cdev, &sc_cdevsw, NULL); 733262182Semaste 734314564Sdim#ifdef DEVFS 735314564Sdim for (vc = 0; vc < MAXCONS; vc++) 736262182Semaste sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR, 737341825Sdim UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc); 738341825Sdim sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR, 739314564Sdim UID_ROOT, GID_WHEEL, 0600, "sysmouse"); 740314564Sdim sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR, 741314564Sdim UID_ROOT, GID_WHEEL, 0600, "consolectl"); 742314564Sdim#endif 743314564Sdim return 0; 744314564Sdim} 745314564Sdim 746314564Sdimstruct tty 747314564Sdim*scdevtotty(dev_t dev) 748314564Sdim{ 749314564Sdim int unit = minor(dev); 750314564Sdim 751314564Sdim if (init_done == COLD) 752314564Sdim return(NULL); 753314564Sdim if (unit == SC_CONSOLE) 754314564Sdim return CONSOLE_TTY; 755314564Sdim if (unit == SC_MOUSE) 756314564Sdim return MOUSE_TTY; 757314564Sdim if (unit >= MAXCONS || unit < 0) 758314564Sdim return(NULL); 759314564Sdim return VIRTUAL_TTY(unit); 760314564Sdim} 761314564Sdim 762341825Sdimint 763314564Sdimscopen(dev_t dev, int flag, int mode, struct proc *p) 764314564Sdim{ 765314564Sdim struct tty *tp = scdevtotty(dev); 766280031Sdim 767262182Semaste if (!tp) 768314564Sdim return(ENXIO); 769314564Sdim 770262182Semaste tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; 771314564Sdim tp->t_param = scparam; 772360784Sdim tp->t_dev = dev; 773314564Sdim if (!(tp->t_state & TS_ISOPEN)) { 774314564Sdim ttychars(tp); 775314564Sdim /* Use the current setting of the <-- key as default VERASE. */ 776314564Sdim /* If the Delete key is preferable, an stty is necessary */ 777314564Sdim tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; 778314564Sdim tp->t_iflag = TTYDEF_IFLAG; 779314564Sdim tp->t_oflag = TTYDEF_OFLAG; 780314564Sdim tp->t_cflag = TTYDEF_CFLAG; 781314564Sdim tp->t_lflag = TTYDEF_LFLAG; 782314564Sdim tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 783314564Sdim scparam(tp, &tp->t_termios); 784314564Sdim (*linesw[tp->t_line].l_modem)(tp, 1); 785314564Sdim if (minor(dev) == SC_MOUSE) 786314564Sdim mouse_level = 0; /* XXX */ 787314564Sdim } 788314564Sdim else 789314564Sdim if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 790314564Sdim return(EBUSY); 791314564Sdim if (minor(dev) < MAXCONS && !console[minor(dev)]) { 792314564Sdim console[minor(dev)] = alloc_scp(); 793314564Sdim if (ISGRAPHSC(console[minor(dev)])) 794314564Sdim sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16); 795314564Sdim } 796314564Sdim if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 797314564Sdim tp->t_winsize.ws_col = console[minor(dev)]->xsize; 798360784Sdim tp->t_winsize.ws_row = console[minor(dev)]->ysize; 799280031Sdim } 800314564Sdim return ((*linesw[tp->t_line].l_open)(dev, tp)); 801314564Sdim} 802314564Sdim 803314564Sdimint 804314564Sdimscclose(dev_t dev, int flag, int mode, struct proc *p) 805314564Sdim{ 806314564Sdim struct tty *tp = scdevtotty(dev); 807314564Sdim struct scr_stat *scp; 808280031Sdim 809314564Sdim if (!tp) 810314564Sdim return(ENXIO); 811314564Sdim if (minor(dev) < MAXCONS) { 812314564Sdim scp = sc_get_scr_stat(tp->t_dev); 813314564Sdim if (scp->status & SWITCH_WAIT_ACQ) 814341825Sdim wakeup((caddr_t)&scp->smode); 815341825Sdim#if not_yet_done 816314564Sdim if (scp == &main_console) { 817314564Sdim scp->pid = 0; 818314564Sdim scp->proc = NULL; 819314564Sdim scp->smode.mode = VT_AUTO; 820314564Sdim } 821314564Sdim else { 822314564Sdim free(scp->scr_buf, M_DEVBUF); 823314564Sdim if (scp->history != NULL) { 824314564Sdim free(scp->history, M_DEVBUF); 825280031Sdim if (scp->history_size / scp->xsize 826280031Sdim > imax(sc_history_size, scp->ysize)) 827314564Sdim extra_history_size += scp->history_size / scp->xsize 828314564Sdim - imax(sc_history_size, scp->ysize); 829309124Sdim } 830360784Sdim free(scp, M_DEVBUF); 831309124Sdim console[minor(dev)] = NULL; 832309124Sdim } 833314564Sdim#else 834314564Sdim scp->pid = 0; 835309124Sdim scp->proc = NULL; 836360784Sdim scp->smode.mode = VT_AUTO; 837309124Sdim#endif 838309124Sdim } 839314564Sdim spltty(); 840314564Sdim (*linesw[tp->t_line].l_close)(tp, flag); 841314564Sdim ttyclose(tp); 842296417Sdim spl0(); 843314564Sdim return(0); 844314564Sdim} 845314564Sdim 846314564Sdimint 847314564Sdimscread(dev_t dev, struct uio *uio, int flag) 848296417Sdim{ 849314564Sdim struct tty *tp = scdevtotty(dev); 850314564Sdim 851314564Sdim if (!tp) 852314564Sdim return(ENXIO); 853314564Sdim return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 854280031Sdim} 855314564Sdim 856314564Sdimint 857314564Sdimscwrite(dev_t dev, struct uio *uio, int flag) 858296417Sdim{ 859314564Sdim struct tty *tp = scdevtotty(dev); 860314564Sdim 861314564Sdim if (!tp) 862314564Sdim return(ENXIO); 863314564Sdim return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 864314564Sdim} 865314564Sdim 866296417Sdimstatic void 867314564Sdimscintr(int unit) 868296417Sdim{ 869314564Sdim static struct tty *cur_tty; 870296417Sdim int c, len; 871296417Sdim u_char *cp; 872314564Sdim 873314564Sdim /* 874314564Sdim * Loop while there is still input to get from the keyboard. 875314564Sdim * I don't think this is nessesary, and it doesn't fix 876314564Sdim * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 877341825Sdim */ 878314564Sdim while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { 879314564Sdim 880314564Sdim cur_tty = VIRTUAL_TTY(get_scr_num()); 881314564Sdim if (!(cur_tty->t_state & TS_ISOPEN)) 882280031Sdim if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 883280031Sdim continue; 884314564Sdim 885314564Sdim switch (c & 0xff00) { 886314564Sdim case 0x0000: /* normal key */ 887314564Sdim (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 888314564Sdim break; 889314564Sdim case FKEY: /* function key, return string */ 890314564Sdim if (cp = get_fstr((u_int)c, (u_int *)&len)) { 891262182Semaste while (len-- > 0) 892314564Sdim (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 893314564Sdim } 894314564Sdim break; 895280031Sdim case MKEY: /* meta is active, prepend ESC */ 896262182Semaste (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 897314564Sdim (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 898314564Sdim break; 899314564Sdim case BKEY: /* backtab fixed sequence (esc [ Z) */ 900314564Sdim (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 901314564Sdim (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 902314564Sdim (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 903280031Sdim break; 904262182Semaste } 905314564Sdim } 906314564Sdim 907314564Sdim#if 0 908314564Sdim if (cur_console->status & MOUSE_ENABLED) { 909314564Sdim cur_console->status &= ~MOUSE_VISIBLE; 910314564Sdim remove_mouse_image(cur_console); 911262182Semaste } 912262182Semaste#else 913344779Sdim if (cur_console->status & MOUSE_VISIBLE) { 914344779Sdim remove_mouse_image(cur_console); 915360784Sdim cur_console->status &= ~MOUSE_VISIBLE; 916360784Sdim } 917360784Sdim#endif 918360784Sdim} 919360784Sdim 920360784Sdimstatic int 921360784Sdimscparam(struct tty *tp, struct termios *t) 922360784Sdim{ 923360784Sdim tp->t_ispeed = t->c_ispeed; 924360784Sdim tp->t_ospeed = t->c_ospeed; 925360784Sdim tp->t_cflag = t->c_cflag; 926344779Sdim return 0; 927360784Sdim} 928360784Sdim 929360784Sdimint 930360784Sdimscioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 931360784Sdim{ 932360784Sdim u_int delta_ehs; 933360784Sdim int error; 934360784Sdim int i; 935360784Sdim struct tty *tp; 936360784Sdim scr_stat *scp; 937360784Sdim int s; 938360784Sdim 939360784Sdim tp = scdevtotty(dev); 940360784Sdim if (!tp) 941360784Sdim return ENXIO; 942360784Sdim scp = sc_get_scr_stat(tp->t_dev); 943360784Sdim 944360784Sdim /* If there is a user_ioctl function call that first */ 945360784Sdim if (sc_user_ioctl) { 946344779Sdim error = (*sc_user_ioctl)(dev, cmd, data, flag, p); 947344779Sdim if (error != ENOIOCTL) 948360784Sdim return error; 949360784Sdim } 950360784Sdim 951360784Sdim error = sc_vid_ioctl(tp, cmd, data, flag, p); 952344779Sdim if (error != ENOIOCTL) 953360784Sdim return error; 954344779Sdim 955360784Sdim switch (cmd) { /* process console hardware related ioctl's */ 956360784Sdim 957360784Sdim case GIO_ATTR: /* get current attributes */ 958360784Sdim *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 959360784Sdim return 0; 960360784Sdim 961360784Sdim case GIO_COLOR: /* is this a color console ? */ 962360784Sdim *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0; 963360784Sdim return 0; 964360784Sdim 965360784Sdim case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 966360784Sdim if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) 967360784Sdim return EINVAL; 968344779Sdim s = spltty(); 969344779Sdim scrn_blank_time = *(int *)data; 970344779Sdim run_scrn_saver = (scrn_blank_time != 0); 971314564Sdim splx(s); 972314564Sdim return 0; 973314564Sdim 974314564Sdim case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 975314564Sdim if ((*(int*)data) & 0x01) 976314564Sdim sc_flags |= BLINK_CURSOR; 977360784Sdim else 978360784Sdim sc_flags &= ~BLINK_CURSOR; 979360784Sdim if ((*(int*)data) & 0x02) { 980360784Sdim if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 981360784Sdim return ENXIO; 982314564Sdim sc_flags |= CHAR_CURSOR; 983360784Sdim } else 984360784Sdim sc_flags &= ~CHAR_CURSOR; 985360784Sdim /* 986360784Sdim * The cursor shape is global property; all virtual consoles 987360784Sdim * are affected. Update the cursor in the current console... 988360784Sdim */ 989360784Sdim if (!ISGRAPHSC(cur_console)) { 990360784Sdim s = spltty(); 991314564Sdim remove_cursor_image(cur_console); 992360784Sdim if (sc_flags & CHAR_CURSOR) 993360784Sdim set_destructive_cursor(cur_console); 994360784Sdim draw_cursor_image(cur_console); 995360784Sdim splx(s); 996360784Sdim } 997360784Sdim return 0; 998360784Sdim 999360784Sdim case CONS_BELLTYPE: /* set bell type sound/visual */ 1000360784Sdim if ((*(int *)data) & 0x01) 1001360784Sdim sc_flags |= VISUAL_BELL; 1002360784Sdim else 1003360784Sdim sc_flags &= ~VISUAL_BELL; 1004360784Sdim if ((*(int *)data) & 0x02) 1005360784Sdim sc_flags |= QUIET_BELL; 1006360784Sdim else 1007360784Sdim sc_flags &= ~QUIET_BELL; 1008360784Sdim return 0; 1009360784Sdim 1010360784Sdim case CONS_HISTORY: /* set history size */ 1011360784Sdim if (*(int *)data > 0) { 1012360784Sdim int lines; /* buffer size to allocate */ 1013360784Sdim int lines0; /* current buffer size */ 1014360784Sdim 1015360784Sdim lines = imax(*(int *)data, scp->ysize); 1016360784Sdim lines0 = (scp->history != NULL) ? 1017314564Sdim scp->history_size / scp->xsize : scp->ysize; 1018314564Sdim if (lines0 > imax(sc_history_size, scp->ysize)) 1019314564Sdim delta_ehs = lines0 - imax(sc_history_size, scp->ysize); 1020314564Sdim else 1021360784Sdim delta_ehs = 0; 1022360784Sdim /* 1023360784Sdim * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE 1024360784Sdim * lines or scp->ysize lines, whichever is larger. A value 1025360784Sdim * greater than that is allowed, subject to extra_history_size. 1026360784Sdim */ 1027314564Sdim if (lines > imax(sc_history_size, scp->ysize)) 1028314564Sdim if (lines - imax(sc_history_size, scp->ysize) > 1029314564Sdim extra_history_size + delta_ehs) 1030360784Sdim return EINVAL; 1031314564Sdim if (cur_console->status & BUFFER_SAVED) 1032360784Sdim return EBUSY; 1033360784Sdim sc_alloc_history_buffer(scp, lines, delta_ehs, TRUE); 1034314564Sdim return 0; 1035280031Sdim } 1036280031Sdim else 1037314564Sdim return EINVAL; 1038314564Sdim 1039314564Sdim case CONS_MOUSECTL: /* control mouse arrow */ 1040314564Sdim case OLD_CONS_MOUSECTL: 1041280031Sdim { 1042314564Sdim /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 1043341825Sdim static int butmap[8] = { 1044341825Sdim MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1045341825Sdim MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1046314564Sdim MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 1047314564Sdim MOUSE_MSC_BUTTON3UP, 1048314564Sdim MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 1049280031Sdim MOUSE_MSC_BUTTON2UP, 1050314564Sdim MOUSE_MSC_BUTTON1UP, 1051314564Sdim 0, 1052314564Sdim }; 1053309124Sdim mouse_info_t *mouse = (mouse_info_t*)data; 1054314564Sdim mouse_info_t buf; 1055353358Sdim 1056353358Sdim /* FIXME: */ 1057353358Sdim if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags)) 1058314564Sdim return ENODEV; 1059314564Sdim 1060314564Sdim if (cmd == OLD_CONS_MOUSECTL) { 1061314564Sdim static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 1062314564Sdim old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 1063314564Sdim 1064314564Sdim mouse = &buf; 1065314564Sdim mouse->operation = old_mouse->operation; 1066314564Sdim switch (mouse->operation) { 1067280031Sdim case MOUSE_MODE: 1068314564Sdim mouse->u.mode = old_mouse->u.mode; 1069321369Sdim break; 1070314564Sdim case MOUSE_SHOW: 1071314564Sdim case MOUSE_HIDE: 1072280031Sdim break; 1073341825Sdim case MOUSE_MOVEABS: 1074341825Sdim case MOUSE_MOVEREL: 1075314564Sdim case MOUSE_ACTION: 1076314564Sdim mouse->u.data.x = old_mouse->u.data.x; 1077314564Sdim mouse->u.data.y = old_mouse->u.data.y; 1078314564Sdim mouse->u.data.z = 0; 1079314564Sdim mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 1080314564Sdim break; 1081314564Sdim case MOUSE_GETINFO: 1082314564Sdim old_mouse->u.data.x = scp->mouse_xpos; 1083314564Sdim old_mouse->u.data.y = scp->mouse_ypos; 1084314564Sdim old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 1085314564Sdim break; 1086314564Sdim default: 1087314564Sdim return EINVAL; 1088314564Sdim } 1089314564Sdim } 1090314564Sdim 1091314564Sdim switch (mouse->operation) { 1092314564Sdim case MOUSE_MODE: 1093314564Sdim if (ISSIGVALID(mouse->u.mode.signal)) { 1094314564Sdim scp->mouse_signal = mouse->u.mode.signal; 1095314564Sdim scp->mouse_proc = p; 1096314564Sdim scp->mouse_pid = p->p_pid; 1097314564Sdim } 1098314564Sdim else { 1099314564Sdim scp->mouse_signal = 0; 1100314564Sdim scp->mouse_proc = NULL; 1101314564Sdim scp->mouse_pid = 0; 1102314564Sdim } 1103314564Sdim return 0; 1104314564Sdim 1105314564Sdim case MOUSE_SHOW: 1106314564Sdim if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) { 1107314564Sdim scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); 1108314564Sdim scp->mouse_oldpos = scp->mouse_pos; 1109314564Sdim mark_all(scp); 1110314564Sdim return 0; 1111314564Sdim } 1112314564Sdim else 1113314564Sdim return EINVAL; 1114314564Sdim break; 1115314564Sdim 1116314564Sdim case MOUSE_HIDE: 1117314564Sdim if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) { 1118314564Sdim scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 1119314564Sdim mark_all(scp); 1120314564Sdim return 0; 1121314564Sdim } 1122314564Sdim else 1123314564Sdim return EINVAL; 1124314564Sdim break; 1125314564Sdim 1126314564Sdim case MOUSE_MOVEABS: 1127314564Sdim scp->mouse_xpos = mouse->u.data.x; 1128314564Sdim scp->mouse_ypos = mouse->u.data.y; 1129314564Sdim set_mouse_pos(scp); 1130314564Sdim break; 1131314564Sdim 1132341825Sdim case MOUSE_MOVEREL: 1133341825Sdim scp->mouse_xpos += mouse->u.data.x; 1134341825Sdim scp->mouse_ypos += mouse->u.data.y; 1135341825Sdim set_mouse_pos(scp); 1136341825Sdim break; 1137314564Sdim 1138314564Sdim case MOUSE_GETINFO: 1139314564Sdim mouse->u.data.x = scp->mouse_xpos; 1140314564Sdim mouse->u.data.y = scp->mouse_ypos; 1141314564Sdim mouse->u.data.z = 0; 1142314564Sdim mouse->u.data.buttons = scp->mouse_buttons; 1143314564Sdim return 0; 1144314564Sdim 1145314564Sdim case MOUSE_ACTION: 1146314564Sdim case MOUSE_MOTION_EVENT: 1147314564Sdim /* this should maybe only be settable from /dev/consolectl SOS */ 1148314564Sdim /* send out mouse event on /dev/sysmouse */ 1149314564Sdim 1150314564Sdim mouse_status.dx += mouse->u.data.x; 1151314564Sdim mouse_status.dy += mouse->u.data.y; 1152314564Sdim mouse_status.dz += mouse->u.data.z; 1153314564Sdim if (mouse->operation == MOUSE_ACTION) 1154314564Sdim mouse_status.button = mouse->u.data.buttons; 1155314564Sdim mouse_status.flags |= 1156360784Sdim ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 1157360784Sdim MOUSE_POSCHANGED : 0) 1158360784Sdim | (mouse_status.obutton ^ mouse_status.button); 1159360784Sdim if (mouse_status.flags == 0) 1160360784Sdim return 0; 1161360784Sdim 1162360784Sdim if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) 1163360784Sdim cur_console->status |= MOUSE_VISIBLE; 1164360784Sdim 1165314564Sdim if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1166314564Sdim u_char buf[MOUSE_SYS_PACKETSIZE]; 1167353358Sdim int j; 1168314564Sdim 1169314564Sdim /* the first five bytes are compatible with MouseSystems' */ 1170314564Sdim buf[0] = MOUSE_MSC_SYNC 1171314564Sdim | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1172314564Sdim j = imax(imin(mouse->u.data.x, 255), -256); 1173314564Sdim buf[1] = j >> 1; 1174314564Sdim buf[3] = j - buf[1]; 1175314564Sdim j = -imax(imin(mouse->u.data.y, 255), -256); 1176314564Sdim buf[2] = j >> 1; 1177314564Sdim buf[4] = j - buf[2]; 1178314564Sdim for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) 1179314564Sdim (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1180314564Sdim if (mouse_level >= 1) { /* extended part */ 1181314564Sdim j = imax(imin(mouse->u.data.z, 127), -128); 1182314564Sdim buf[5] = (j >> 1) & 0x7f; 1183314564Sdim buf[6] = (j - (j >> 1)) & 0x7f; 1184280031Sdim /* buttons 4-10 */ 1185314564Sdim buf[7] = (~mouse_status.button >> 3) & 0x7f; 1186280031Sdim for (j = MOUSE_MSC_PACKETSIZE; 1187314564Sdim j < MOUSE_SYS_PACKETSIZE; j++) 1188314564Sdim (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1189314564Sdim } 1190314564Sdim } 1191314564Sdim 1192314564Sdim if (cur_console->mouse_signal) { 1193314564Sdim cur_console->mouse_buttons = mouse->u.data.buttons; 1194314564Sdim /* has controlling process died? */ 1195314564Sdim if (cur_console->mouse_proc && 1196314564Sdim (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1197314564Sdim cur_console->mouse_signal = 0; 1198314564Sdim cur_console->mouse_proc = NULL; 1199280031Sdim cur_console->mouse_pid = 0; 1200314564Sdim } 1201314564Sdim else 1202314564Sdim psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1203314564Sdim } 1204314564Sdim else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) { 1205314564Sdim /* process button presses */ 1206314564Sdim if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 1207314564Sdim ISTEXTSC(cur_console)) { 1208314564Sdim cur_console->mouse_buttons = mouse->u.data.buttons; 1209314564Sdim if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) 1210314564Sdim mouse_cut_start(cur_console); 1211314564Sdim else 1212314564Sdim mouse_cut_end(cur_console); 1213314564Sdim if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || 1214314564Sdim cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) 1215314564Sdim mouse_paste(cur_console); 1216314564Sdim } 1217314564Sdim } 1218314564Sdim 1219314564Sdim if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 1220314564Sdim cur_console->mouse_xpos += mouse->u.data.x; 1221314564Sdim cur_console->mouse_ypos += mouse->u.data.y; 1222314564Sdim set_mouse_pos(cur_console); 1223314564Sdim } 1224314564Sdim 1225314564Sdim break; 1226341825Sdim 1227314564Sdim case MOUSE_BUTTON_EVENT: 1228314564Sdim if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 1229314564Sdim return EINVAL; 1230280031Sdim if (mouse->u.event.value < 0) 1231314564Sdim return EINVAL; 1232262182Semaste 1233262182Semaste if (mouse->u.event.value > 0) { 1234280031Sdim cur_console->mouse_buttons |= mouse->u.event.id; 1235280031Sdim mouse_status.button |= mouse->u.event.id; 1236314564Sdim } else { 1237314564Sdim cur_console->mouse_buttons &= ~mouse->u.event.id; 1238314564Sdim mouse_status.button &= ~mouse->u.event.id; 1239314564Sdim } 1240262182Semaste mouse_status.flags |= mouse_status.obutton ^ mouse_status.button; 1241262182Semaste if (mouse_status.flags == 0) 1242314564Sdim return 0; 1243314564Sdim 1244314564Sdim if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) 1245314564Sdim cur_console->status |= MOUSE_VISIBLE; 1246314564Sdim 1247314564Sdim if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1248314564Sdim u_char buf[8]; 1249314564Sdim int i; 1250309124Sdim 1251309124Sdim buf[0] = MOUSE_MSC_SYNC 1252314564Sdim | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1253314564Sdim buf[7] = (~mouse_status.button >> 3) & 0x7f; 1254314564Sdim buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 1255314564Sdim for (i = 0; 1256314564Sdim i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 1257321369Sdim : MOUSE_MSC_PACKETSIZE); i++) 1258321369Sdim (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); 1259314564Sdim } 1260314564Sdim 1261314564Sdim if (cur_console->mouse_signal) { 1262314564Sdim if (cur_console->mouse_proc && 1263314564Sdim (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1264314564Sdim cur_console->mouse_signal = 0; 1265309124Sdim cur_console->mouse_proc = NULL; 1266314564Sdim cur_console->mouse_pid = 0; 1267314564Sdim } 1268314564Sdim else 1269314564Sdim psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1270314564Sdim break; 1271314564Sdim } 1272314564Sdim 1273314564Sdim if (!ISTEXTSC(cur_console) || (cut_buffer == NULL)) 1274309124Sdim break; 1275314564Sdim 1276309124Sdim switch (mouse->u.event.id) { 1277262182Semaste case MOUSE_BUTTON1DOWN: 1278262182Semaste switch (mouse->u.event.value % 4) { 1279314564Sdim case 0: /* up */ 1280314564Sdim mouse_cut_end(cur_console); 1281341825Sdim break; 1282341825Sdim case 1: 1283341825Sdim mouse_cut_start(cur_console); 1284314564Sdim break; 1285314564Sdim case 2: 1286314564Sdim mouse_cut_word(cur_console); 1287314564Sdim break; 1288280031Sdim case 3: 1289341825Sdim mouse_cut_line(cur_console); 1290341825Sdim break; 1291341825Sdim } 1292341825Sdim break; 1293314564Sdim case MOUSE_BUTTON2DOWN: 1294262182Semaste switch (mouse->u.event.value) { 1295262182Semaste case 0: /* up */ 1296314564Sdim break; 1297314564Sdim default: 1298262182Semaste mouse_paste(cur_console); 1299262182Semaste break; 1300314564Sdim } 1301314564Sdim break; 1302314564Sdim case MOUSE_BUTTON3DOWN: 1303280031Sdim switch (mouse->u.event.value) { 1304280031Sdim case 0: /* up */ 1305314564Sdim if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) 1306314564Sdim mouse_cut_end(cur_console); 1307314564Sdim break; 1308314564Sdim default: 1309353358Sdim mouse_cut_extend(cur_console); 1310353358Sdim break; 1311353358Sdim } 1312353358Sdim break; 1313353358Sdim } 1314353358Sdim break; 1315353358Sdim 1316314564Sdim default: 1317314564Sdim return EINVAL; 1318314564Sdim } 1319314564Sdim /* make screensaver happy */ 1320314564Sdim scsplash_stick(FALSE); 1321314564Sdim run_scrn_saver = FALSE; 1322314564Sdim return 0; 1323314564Sdim } 1324314564Sdim 1325314564Sdim /* MOUSE_XXX: /dev/sysmouse ioctls */ 1326280031Sdim case MOUSE_GETHWINFO: /* get device information */ 1327314564Sdim { 1328280031Sdim mousehw_t *hw = (mousehw_t *)data; 1329280031Sdim 1330314564Sdim if (tp != MOUSE_TTY) 1331280031Sdim return ENOTTY; 1332314564Sdim hw->buttons = 10; /* XXX unknown */ 1333280031Sdim hw->iftype = MOUSE_IF_SYSMOUSE; 1334314564Sdim hw->type = MOUSE_MOUSE; 1335314564Sdim hw->model = MOUSE_MODEL_GENERIC; 1336314564Sdim hw->hwid = 0; 1337314564Sdim return 0; 1338314564Sdim } 1339314564Sdim 1340314564Sdim case MOUSE_GETMODE: /* get protocol/mode */ 1341314564Sdim { 1342314564Sdim mousemode_t *mode = (mousemode_t *)data; 1343262182Semaste 1344262182Semaste if (tp != MOUSE_TTY) 1345314564Sdim return ENOTTY; 1346314564Sdim mode->level = mouse_level; 1347314564Sdim switch (mode->level) { 1348314564Sdim case 0: 1349314564Sdim /* at this level, sysmouse emulates MouseSystems protocol */ 1350314564Sdim mode->protocol = MOUSE_PROTO_MSC; 1351314564Sdim mode->rate = -1; /* unknown */ 1352314564Sdim mode->resolution = -1; /* unknown */ 1353314564Sdim mode->accelfactor = 0; /* disabled */ 1354314564Sdim mode->packetsize = MOUSE_MSC_PACKETSIZE; 1355262182Semaste mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 1356280031Sdim mode->syncmask[1] = MOUSE_MSC_SYNC; 1357314564Sdim break; 1358314564Sdim 1359314564Sdim case 1: 1360314564Sdim /* at this level, sysmouse uses its own protocol */ 1361262182Semaste mode->protocol = MOUSE_PROTO_SYSMOUSE; 1362262182Semaste mode->rate = -1; 1363314564Sdim mode->resolution = -1; 1364314564Sdim mode->accelfactor = 0; 1365314564Sdim mode->packetsize = MOUSE_SYS_PACKETSIZE; 1366314564Sdim mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 1367262182Semaste mode->syncmask[1] = MOUSE_SYS_SYNC; 1368262182Semaste break; 1369314564Sdim } 1370314564Sdim return 0; 1371314564Sdim } 1372314564Sdim 1373314564Sdim case MOUSE_SETMODE: /* set protocol/mode */ 1374314564Sdim { 1375314564Sdim mousemode_t *mode = (mousemode_t *)data; 1376262182Semaste 1377262182Semaste if (tp != MOUSE_TTY) 1378314564Sdim return ENOTTY; 1379314564Sdim if ((mode->level < 0) || (mode->level > 1)) 1380314564Sdim return EINVAL; 1381314564Sdim mouse_level = mode->level; 1382288943Sdim return 0; 1383314564Sdim } 1384309124Sdim 1385314564Sdim case MOUSE_GETLEVEL: /* get operation level */ 1386314564Sdim if (tp != MOUSE_TTY) 1387314564Sdim return ENOTTY; 1388314564Sdim *(int *)data = mouse_level; 1389314564Sdim return 0; 1390314564Sdim 1391288943Sdim case MOUSE_SETLEVEL: /* set operation level */ 1392314564Sdim if (tp != MOUSE_TTY) 1393314564Sdim return ENOTTY; 1394314564Sdim if ((*(int *)data < 0) || (*(int *)data > 1)) 1395314564Sdim return EINVAL; 1396280031Sdim mouse_level = *(int *)data; 1397314564Sdim return 0; 1398314564Sdim 1399280031Sdim case MOUSE_GETSTATUS: /* get accumulated mouse events */ 1400314564Sdim if (tp != MOUSE_TTY) 1401314564Sdim return ENOTTY; 1402314564Sdim s = spltty(); 1403314564Sdim *(mousestatus_t *)data = mouse_status; 1404314564Sdim mouse_status.flags = 0; 1405314564Sdim mouse_status.obutton = mouse_status.button; 1406314564Sdim mouse_status.dx = 0; 1407280031Sdim mouse_status.dy = 0; 1408314564Sdim mouse_status.dz = 0; 1409280031Sdim splx(s); 1410314564Sdim return 0; 1411280031Sdim 1412314564Sdim#if notyet 1413262182Semaste case MOUSE_GETVARS: /* get internal mouse variables */ 1414314564Sdim case MOUSE_SETVARS: /* set internal mouse variables */ 1415314564Sdim if (tp != MOUSE_TTY) 1416262182Semaste return ENOTTY; 1417262182Semaste return ENODEV; 1418314564Sdim#endif 1419314564Sdim 1420314564Sdim case MOUSE_READSTATE: /* read status from the device */ 1421309124Sdim case MOUSE_READDATA: /* read data from the device */ 1422341825Sdim if (tp != MOUSE_TTY) 1423341825Sdim return ENOTTY; 1424314564Sdim return ENODEV; 1425314564Sdim 1426314564Sdim case CONS_GETINFO: /* get current (virtual) console info */ 1427280031Sdim { 1428314564Sdim vid_info_t *ptr = (vid_info_t*)data; 1429314564Sdim if (ptr->size == sizeof(struct vid_info)) { 1430314564Sdim ptr->m_num = get_scr_num(); 1431314564Sdim ptr->mv_col = scp->xpos; 1432314564Sdim ptr->mv_row = scp->ypos; 1433314564Sdim ptr->mv_csz = scp->xsize; 1434314564Sdim ptr->mv_rsz = scp->ysize; 1435262182Semaste ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 1436314564Sdim ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 1437314564Sdim ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 1438314564Sdim ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 1439314564Sdim ptr->mv_grfc.fore = 0; /* not supported */ 1440314564Sdim ptr->mv_grfc.back = 0; /* not supported */ 1441314564Sdim ptr->mv_ovscan = scp->border; 1442314564Sdim ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 1443314564Sdim return 0; 1444314564Sdim } 1445314564Sdim return EINVAL; 1446314564Sdim } 1447314564Sdim 1448314564Sdim case CONS_GETVERS: /* get version number */ 1449314564Sdim *(int*)data = 0x200; /* version 2.0 */ 1450314564Sdim return 0; 1451314564Sdim 1452314564Sdim case CONS_IDLE: /* see if the screen has been idle */ 1453262182Semaste /* 1454288943Sdim * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE, 1455314564Sdim * the user process may have been writing something on the 1456314564Sdim * screen and syscons is not aware of it. Declare the screen 1457314564Sdim * is NOT idle if it is in one of these modes. But there is 1458314564Sdim * an exception to it; if a screen saver is running in the 1459314564Sdim * graphics mode in the current screen, we should say that the 1460314564Sdim * screen has been idle. 1461314564Sdim */ 1462314564Sdim *(int *)data = scrn_idle 1463314564Sdim && (!ISGRAPHSC(cur_console) 1464314564Sdim || (cur_console->status & SAVER_RUNNING)); 1465314564Sdim return 0; 1466314564Sdim 1467314564Sdim case CONS_SAVERMODE: /* set saver mode */ 1468314564Sdim switch(*(int *)data) { 1469321369Sdim case CONS_USR_SAVER: 1470314564Sdim /* if a LKM screen saver is running, stop it first. */ 1471314564Sdim scsplash_stick(FALSE); 1472314564Sdim saver_mode = *(int *)data; 1473314564Sdim s = spltty(); 1474321369Sdim if ((error = wait_scrn_saver_stop())) { 1475314564Sdim splx(s); 1476314564Sdim return error; 1477314564Sdim } 1478314564Sdim scp->status |= SAVER_RUNNING; 1479314564Sdim scsplash_stick(TRUE); 1480314564Sdim splx(s); 1481314564Sdim break; 1482314564Sdim case CONS_LKM_SAVER: 1483314564Sdim s = spltty(); 1484314564Sdim if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING)) 1485314564Sdim scp->status &= ~SAVER_RUNNING; 1486314564Sdim saver_mode = *(int *)data; 1487360784Sdim splx(s); 1488314564Sdim break; 1489314564Sdim default: 1490314564Sdim return EINVAL; 1491314564Sdim } 1492314564Sdim return 0; 1493314564Sdim 1494314564Sdim case CONS_SAVERSTART: /* immediately start/stop the screen saver */ 1495314564Sdim /* 1496314564Sdim * Note that this ioctl does not guarantee the screen saver 1497314564Sdim * actually starts or stops. It merely attempts to do so... 1498314564Sdim */ 1499314564Sdim s = spltty(); 1500288943Sdim run_scrn_saver = (*(int *)data != 0); 1501314564Sdim if (run_scrn_saver) 1502314564Sdim scrn_time_stamp -= scrn_blank_time; 1503288943Sdim splx(s); 1504 return 0; 1505 1506 case VT_SETMODE: /* set screen switcher mode */ 1507 { 1508 struct vt_mode *mode; 1509 1510 mode = (struct vt_mode *)data; 1511 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && 1512 ISSIGVALID(mode->frsig)) { 1513 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 1514 if (scp->smode.mode == VT_PROCESS) { 1515 scp->proc = p; 1516 scp->pid = scp->proc->p_pid; 1517 } 1518 return 0; 1519 } else 1520 return EINVAL; 1521 } 1522 1523 case VT_GETMODE: /* get screen switcher mode */ 1524 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 1525 return 0; 1526 1527 case VT_RELDISP: /* screen switcher ioctl */ 1528 switch(*(int *)data) { 1529 case VT_FALSE: /* user refuses to release screen, abort */ 1530 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1531 old_scp->status &= ~SWITCH_WAIT_REL; 1532 switch_in_progress = FALSE; 1533 return 0; 1534 } 1535 return EINVAL; 1536 1537 case VT_TRUE: /* user has released screen, go on */ 1538 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1539 scp->status &= ~SWITCH_WAIT_REL; 1540 exchange_scr(); 1541 if (new_scp->smode.mode == VT_PROCESS) { 1542 new_scp->status |= SWITCH_WAIT_ACQ; 1543 psignal(new_scp->proc, new_scp->smode.acqsig); 1544 } 1545 else 1546 switch_in_progress = FALSE; 1547 return 0; 1548 } 1549 return EINVAL; 1550 1551 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 1552 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 1553 scp->status &= ~SWITCH_WAIT_ACQ; 1554 switch_in_progress = FALSE; 1555 return 0; 1556 } 1557 return EINVAL; 1558 1559 default: 1560 return EINVAL; 1561 } 1562 /* NOT REACHED */ 1563 1564 case VT_OPENQRY: /* return free virtual console */ 1565 for (i = 0; i < MAXCONS; i++) { 1566 tp = VIRTUAL_TTY(i); 1567 if (!(tp->t_state & TS_ISOPEN)) { 1568 *(int *)data = i + 1; 1569 return 0; 1570 } 1571 } 1572 return EINVAL; 1573 1574 case VT_ACTIVATE: /* switch to screen *data */ 1575 return switch_scr(scp, *(int *)data - 1); 1576 1577 case VT_WAITACTIVE: /* wait for switch to occur */ 1578 if (*(int *)data > MAXCONS || *(int *)data < 0) 1579 return EINVAL; 1580 if (minor(dev) == *(int *)data - 1) 1581 return 0; 1582 if (*(int *)data == 0) { 1583 if (scp == cur_console) 1584 return 0; 1585 } 1586 else 1587 scp = console[*(int *)data - 1]; 1588 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1589 "waitvt", 0)) == ERESTART) ; 1590 return error; 1591 1592 case VT_GETACTIVE: 1593 *(int *)data = get_scr_num()+1; 1594 return 0; 1595 1596 case KDENABIO: /* allow io operations */ 1597 error = suser(p->p_ucred, &p->p_acflag); 1598 if (error != 0) 1599 return error; 1600 if (securelevel > 0) 1601 return EPERM; 1602 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 1603 return 0; 1604 1605 case KDDISABIO: /* disallow io operations (default) */ 1606 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 1607 return 0; 1608 1609 case KDSKBSTATE: /* set keyboard state (locks) */ 1610 if (*(int *)data & ~LOCK_KEY_MASK) 1611 return EINVAL; 1612 scp->status &= ~LOCK_KEY_MASK; 1613 scp->status |= *(int *)data; 1614 if (scp == cur_console) 1615 update_leds(scp->status); 1616 return 0; 1617 1618 case KDGKBSTATE: /* get keyboard state (locks) */ 1619 *(int *)data = scp->status & LOCK_KEY_MASK; 1620 return 0; 1621 1622 case KDSETRAD: /* set keyboard repeat & delay rates */ 1623 if (*(int *)data & ~0x7f) 1624 return EINVAL; 1625 if (sc_kbdc != NULL) 1626 set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data); 1627 return 0; 1628 1629 case KDSKBMODE: /* set keyboard mode */ 1630 switch (*(int *)data) { 1631 case K_RAW: /* switch to RAW scancode mode */ 1632 scp->status &= ~KBD_CODE_MODE; 1633 scp->status |= KBD_RAW_MODE; 1634 return 0; 1635 1636 case K_CODE: /* switch to CODE mode */ 1637 scp->status &= ~KBD_RAW_MODE; 1638 scp->status |= KBD_CODE_MODE; 1639 return 0; 1640 1641 case K_XLATE: /* switch to XLT ascii mode */ 1642 if (scp == cur_console && scp->status & KBD_RAW_MODE) 1643 shfts = ctls = alts = agrs = metas = accents = 0; 1644 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); 1645 return 0; 1646 default: 1647 return EINVAL; 1648 } 1649 /* NOT REACHED */ 1650 1651 case KDGKBMODE: /* get keyboard mode */ 1652 *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : 1653 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); 1654 return 0; 1655 1656 case KDMKTONE: /* sound the bell */ 1657 if (*(int*)data) 1658 do_bell(scp, (*(int*)data)&0xffff, 1659 (((*(int*)data)>>16)&0xffff)*hz/1000); 1660 else 1661 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1662 return 0; 1663 1664 case KIOCSOUND: /* make tone (*data) hz */ 1665 if (scp == cur_console) { 1666 if (*(int*)data) { 1667 int pitch = timer_freq / *(int*)data; 1668 1669 /* set command for counter 2, 2 byte write */ 1670 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1671 return EBUSY; 1672 1673 /* set pitch */ 1674 outb(TIMER_CNTR2, pitch); 1675 outb(TIMER_CNTR2, (pitch>>8)); 1676 1677 /* enable counter 2 output to speaker */ 1678 outb(IO_PPI, inb(IO_PPI) | 3); 1679 } 1680 else { 1681 /* disable counter 2 output to speaker */ 1682 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1683 release_timer2(); 1684 } 1685 } 1686 return 0; 1687 1688 case KDGKBTYPE: /* get keyboard type */ 1689 *(int *)data = 0; /* type not known (yet) */ 1690 return 0; 1691 1692 case KDSETLED: /* set keyboard LED status */ 1693 if (*(int *)data & ~LED_MASK) 1694 return EINVAL; 1695 scp->status &= ~LED_MASK; 1696 scp->status |= *(int *)data; 1697 if (scp == cur_console) 1698 update_leds(scp->status); 1699 return 0; 1700 1701 case KDGETLED: /* get keyboard LED status */ 1702 *(int *)data = scp->status & LED_MASK; 1703 return 0; 1704 1705 case GETFKEY: /* get functionkey string */ 1706 if (*(u_short*)data < n_fkey_tab) { 1707 fkeyarg_t *ptr = (fkeyarg_t*)data; 1708 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1709 fkey_tab[ptr->keynum].len); 1710 ptr->flen = fkey_tab[ptr->keynum].len; 1711 return 0; 1712 } 1713 else 1714 return EINVAL; 1715 1716 case SETFKEY: /* set functionkey string */ 1717 if (*(u_short*)data < n_fkey_tab) { 1718 fkeyarg_t *ptr = (fkeyarg_t*)data; 1719 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1720 min(ptr->flen, MAXFK)); 1721 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1722 return 0; 1723 } 1724 else 1725 return EINVAL; 1726 1727 case GIO_SCRNMAP: /* get output translation table */ 1728 bcopy(&scr_map, data, sizeof(scr_map)); 1729 return 0; 1730 1731 case PIO_SCRNMAP: /* set output translation table */ 1732 bcopy(data, &scr_map, sizeof(scr_map)); 1733 for (i=0; i<sizeof(scr_map); i++) 1734 scr_rmap[scr_map[i]] = i; 1735 return 0; 1736 1737 case GIO_KEYMAP: /* get keyboard translation table */ 1738 bcopy(&key_map, data, sizeof(key_map)); 1739 return 0; 1740 1741 case PIO_KEYMAP: /* set keyboard translation table */ 1742 accents = 0; 1743 bzero(&accent_map, sizeof(accent_map)); 1744 bcopy(data, &key_map, sizeof(key_map)); 1745 return 0; 1746 1747 case GIO_DEADKEYMAP: /* get accent key translation table */ 1748 bcopy(&accent_map, data, sizeof(accent_map)); 1749 return 0; 1750 1751 case PIO_DEADKEYMAP: /* set accent key translation table */ 1752 accents = 0; 1753 bcopy(data, &accent_map, sizeof(accent_map)); 1754 return 0; 1755 1756 case PIO_FONT8x8: /* set 8x8 dot font */ 1757 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1758 return ENXIO; 1759 bcopy(data, font_8, 8*256); 1760 fonts_loaded |= FONT_8; 1761 /* 1762 * FONT KLUDGE 1763 * Always use the font page #0. XXX 1764 * Don't load if the current font size is not 8x8. 1765 */ 1766 if (ISTEXTSC(cur_console) && (cur_console->font_size < 14)) 1767 copy_font(cur_console, LOAD, 8, font_8); 1768 return 0; 1769 1770 case GIO_FONT8x8: /* get 8x8 dot font */ 1771 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1772 return ENXIO; 1773 if (fonts_loaded & FONT_8) { 1774 bcopy(font_8, data, 8*256); 1775 return 0; 1776 } 1777 else 1778 return ENXIO; 1779 1780 case PIO_FONT8x14: /* set 8x14 dot font */ 1781 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1782 return ENXIO; 1783 bcopy(data, font_14, 14*256); 1784 fonts_loaded |= FONT_14; 1785 /* 1786 * FONT KLUDGE 1787 * Always use the font page #0. XXX 1788 * Don't load if the current font size is not 8x14. 1789 */ 1790 if (ISTEXTSC(cur_console) 1791 && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) 1792 copy_font(cur_console, LOAD, 14, font_14); 1793 return 0; 1794 1795 case GIO_FONT8x14: /* get 8x14 dot font */ 1796 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1797 return ENXIO; 1798 if (fonts_loaded & FONT_14) { 1799 bcopy(font_14, data, 14*256); 1800 return 0; 1801 } 1802 else 1803 return ENXIO; 1804 1805 case PIO_FONT8x16: /* set 8x16 dot font */ 1806 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1807 return ENXIO; 1808 bcopy(data, font_16, 16*256); 1809 fonts_loaded |= FONT_16; 1810 /* 1811 * FONT KLUDGE 1812 * Always use the font page #0. XXX 1813 * Don't load if the current font size is not 8x16. 1814 */ 1815 if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16)) 1816 copy_font(cur_console, LOAD, 16, font_16); 1817 return 0; 1818 1819 case GIO_FONT8x16: /* get 8x16 dot font */ 1820 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1821 return ENXIO; 1822 if (fonts_loaded & FONT_16) { 1823 bcopy(font_16, data, 16*256); 1824 return 0; 1825 } 1826 else 1827 return ENXIO; 1828 default: 1829 break; 1830 } 1831 1832 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1833 if (error != ENOIOCTL) 1834 return(error); 1835 error = ttioctl(tp, cmd, data, flag); 1836 if (error != ENOIOCTL) 1837 return(error); 1838 return(ENOTTY); 1839} 1840 1841static void 1842scstart(struct tty *tp) 1843{ 1844 struct clist *rbp; 1845 int s, len; 1846 u_char buf[PCBURST]; 1847 scr_stat *scp = sc_get_scr_stat(tp->t_dev); 1848 1849 if (scp->status & SLKED || blink_in_progress) 1850 return; /* XXX who repeats the call when the above flags are cleared? */ 1851 s = spltty(); 1852 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1853 tp->t_state |= TS_BUSY; 1854 rbp = &tp->t_outq; 1855 while (rbp->c_cc) { 1856 len = q_to_b(rbp, buf, PCBURST); 1857 splx(s); 1858 ansi_put(scp, buf, len); 1859 s = spltty(); 1860 } 1861 tp->t_state &= ~TS_BUSY; 1862 ttwwakeup(tp); 1863 } 1864 splx(s); 1865} 1866 1867static void 1868scmousestart(struct tty *tp) 1869{ 1870 struct clist *rbp; 1871 int s; 1872 u_char buf[PCBURST]; 1873 1874 s = spltty(); 1875 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1876 tp->t_state |= TS_BUSY; 1877 rbp = &tp->t_outq; 1878 while (rbp->c_cc) { 1879 q_to_b(rbp, buf, PCBURST); 1880 } 1881 tp->t_state &= ~TS_BUSY; 1882 ttwwakeup(tp); 1883 } 1884 splx(s); 1885} 1886 1887static void 1888sccnprobe(struct consdev *cp) 1889{ 1890 struct isa_device *dvp; 1891 1892 /* 1893 * Take control if we are the highest priority enabled display device. 1894 */ 1895 dvp = find_display(); 1896 if (dvp == NULL || dvp->id_driver != &scdriver) { 1897 cp->cn_pri = CN_DEAD; 1898 return; 1899 } 1900 1901 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { 1902 cp->cn_pri = CN_DEAD; 1903 return; 1904 } 1905 1906 /* initialize required fields */ 1907 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 1908 cp->cn_pri = CN_INTERNAL; 1909 1910 sc_kbdc = kbdc_open(sc_port); 1911} 1912 1913static void 1914sccninit(struct consdev *cp) 1915{ 1916 scinit(); 1917} 1918 1919static void 1920sccnputc(dev_t dev, int c) 1921{ 1922 u_char buf[1]; 1923 int s; 1924 scr_stat *scp = console[0]; 1925 term_stat save = scp->term; 1926 1927 scp->term = kernel_console; 1928 current_default = &kernel_default; 1929 if (scp == cur_console && !ISGRAPHSC(scp)) 1930 remove_cursor_image(scp); 1931 buf[0] = c; 1932 ansi_put(scp, buf, 1); 1933 kernel_console = scp->term; 1934 current_default = &user_default; 1935 scp->term = save; 1936 1937 s = spltty(); /* block scintr and scrn_timer */ 1938 sccnupdate(scp); 1939 splx(s); 1940} 1941 1942static int 1943sccngetc(dev_t dev) 1944{ 1945 int s = spltty(); /* block scintr and scrn_timer while we poll */ 1946 int c; 1947 1948 /* 1949 * Stop the screen saver and update the screen if necessary. 1950 * What if we have been running in the screen saver code... XXX 1951 */ 1952 scsplash_stick(FALSE); 1953 run_scrn_saver = FALSE; 1954 sccnupdate(cur_console); 1955 1956 c = scgetc(SCGETC_CN); 1957 splx(s); 1958 return(c); 1959} 1960 1961static int 1962sccncheckc(dev_t dev) 1963{ 1964 int s = spltty(); /* block scintr and scrn_timer while we poll */ 1965 int c; 1966 1967 scsplash_stick(FALSE); 1968 run_scrn_saver = FALSE; 1969 sccnupdate(cur_console); 1970 1971 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); 1972 splx(s); 1973 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ 1974} 1975 1976static void 1977sccnupdate(scr_stat *scp) 1978{ 1979 /* this is a cut-down version of scrn_timer()... */ 1980 1981 if (font_loading_in_progress) 1982 return; 1983 1984 if (panicstr || shutdown_in_progress) { 1985 scsplash_stick(FALSE); 1986 run_scrn_saver = FALSE; 1987 } else if (scp != cur_console) { 1988 return; 1989 } 1990 1991 if (!run_scrn_saver) 1992 scrn_idle = FALSE; 1993 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 1994 if (scp->status & SAVER_RUNNING) 1995 stop_scrn_saver(current_saver); 1996 1997 if (scp != cur_console || blink_in_progress || switch_in_progress) 1998 return; 1999 2000 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 2001 scrn_update(scp, TRUE); 2002} 2003 2004scr_stat 2005*sc_get_scr_stat(dev_t dev) 2006{ 2007 int unit = minor(dev); 2008 2009 if (unit == SC_CONSOLE) 2010 return console[0]; 2011 if (unit >= MAXCONS || unit < 0) 2012 return(NULL); 2013 return console[unit]; 2014} 2015 2016static int 2017get_scr_num() 2018{ 2019 int i = 0; 2020 2021 while ((i < MAXCONS) && (cur_console != console[i])) 2022 i++; 2023 return i < MAXCONS ? i : 0; 2024} 2025 2026static void 2027scrn_timer(void *arg) 2028{ 2029 struct timeval tv; 2030 scr_stat *scp; 2031 int s; 2032 2033 /* don't do anything when we are touching font */ 2034 if (font_loading_in_progress) { 2035 if (arg) 2036 timeout(scrn_timer, (void *)TRUE, hz / 10); 2037 return; 2038 } 2039 s = spltty(); 2040 2041 /* 2042 * With release 2.1 of the Xaccel server, the keyboard is left 2043 * hanging pretty often. Apparently an interrupt from the 2044 * keyboard is lost, and I don't know why (yet). 2045 * This ugly hack calls scintr if input is ready for the keyboard 2046 * and conveniently hides the problem. XXX 2047 */ 2048 /* Try removing anything stuck in the keyboard controller; whether 2049 * it's a keyboard scan code or mouse data. `scintr()' doesn't 2050 * read the mouse data directly, but `kbdio' routines will, as a 2051 * side effect. 2052 */ 2053 if (kbdc_lock(sc_kbdc, TRUE)) { 2054 /* 2055 * We have seen the lock flag is not set. Let's reset the flag early; 2056 * otherwise `update_led()' failes which may want the lock 2057 * during `scintr()'. 2058 */ 2059 kbdc_lock(sc_kbdc, FALSE); 2060 if (kbdc_data_ready(sc_kbdc)) 2061 scintr(0); 2062 } 2063 2064 scp = cur_console; 2065 2066 /* should we stop the screen saver? */ 2067 getmicrouptime(&tv); 2068 if (panicstr || shutdown_in_progress) { 2069 scsplash_stick(FALSE); 2070 run_scrn_saver = FALSE; 2071 } 2072 if (run_scrn_saver) { 2073 scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time); 2074 } else { 2075 scrn_time_stamp = tv.tv_sec; 2076 scrn_idle = FALSE; 2077 if (scrn_blank_time > 0) 2078 run_scrn_saver = TRUE; 2079 } 2080 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 2081 if (scp->status & SAVER_RUNNING) 2082 stop_scrn_saver(current_saver); 2083 2084 /* should we just return ? */ 2085 if (blink_in_progress || switch_in_progress) { 2086 if (arg) 2087 timeout(scrn_timer, (void *)TRUE, hz / 10); 2088 splx(s); 2089 return; 2090 } 2091 2092 /* Update the screen */ 2093 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 2094 scrn_update(scp, TRUE); 2095 2096 /* should we activate the screen saver? */ 2097 if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) 2098 if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING)) 2099 scrn_saver(current_saver, TRUE); 2100 2101 if (arg) 2102 timeout(scrn_timer, (void *)TRUE, hz / 25); 2103 splx(s); 2104} 2105 2106static void 2107scrn_update(scr_stat *scp, int show_cursor) 2108{ 2109 /* update screen image */ 2110 if (scp->start <= scp->end) 2111 sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0); 2112 2113 /* we are not to show the cursor and the mouse pointer... */ 2114 if (!show_cursor) { 2115 scp->end = 0; 2116 scp->start = scp->xsize*scp->ysize - 1; 2117 return; 2118 } 2119 2120 /* update "pseudo" mouse pointer image */ 2121 if (scp->status & MOUSE_VISIBLE) { 2122 /* did mouse move since last time ? */ 2123 if (scp->status & MOUSE_MOVED) { 2124 /* do we need to remove old mouse pointer image ? */ 2125 if (scp->mouse_cut_start != NULL || 2126 (scp->mouse_pos-scp->scr_buf) <= scp->start || 2127 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) { 2128 remove_mouse_image(scp); 2129 } 2130 scp->status &= ~MOUSE_MOVED; 2131 draw_mouse_image(scp); 2132 } 2133 else { 2134 /* mouse didn't move, has it been overwritten ? */ 2135 if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start && 2136 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 2137 draw_mouse_image(scp); 2138 } 2139 } 2140 } 2141 2142 /* update cursor image */ 2143 if (scp->status & CURSOR_ENABLED) { 2144 /* did cursor move since last time ? */ 2145 if (scp->cursor_pos != scp->cursor_oldpos) { 2146 /* do we need to remove old cursor image ? */ 2147 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 2148 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 2149 remove_cursor_image(scp); 2150 } 2151 scp->cursor_oldpos = scp->cursor_pos; 2152 draw_cursor_image(scp); 2153 } 2154 else { 2155 /* cursor didn't move, has it been overwritten ? */ 2156 if (scp->cursor_pos - scp->scr_buf >= scp->start && 2157 scp->cursor_pos - scp->scr_buf <= scp->end) { 2158 draw_cursor_image(scp); 2159 } else { 2160 /* if its a blinking cursor, we may have to update it */ 2161 if (sc_flags & BLINK_CURSOR) 2162 draw_cursor_image(scp); 2163 } 2164 } 2165 blinkrate++; 2166 } 2167 2168 if (scp->mouse_cut_start != NULL) 2169 draw_cutmarking(scp); 2170 2171 scp->end = 0; 2172 scp->start = scp->xsize*scp->ysize - 1; 2173} 2174 2175int 2176add_scrn_saver(void (*this_saver)(int)) 2177{ 2178#ifdef SC_SPLASH_SCREEN 2179 if (current_saver == scsplash) { 2180 scsplash_stick(FALSE); 2181 stop_scrn_saver(scsplash); 2182 } 2183#endif 2184 2185 if (current_saver != default_saver) 2186 return EBUSY; 2187 run_scrn_saver = FALSE; 2188 saver_mode = CONS_LKM_SAVER; 2189 current_saver = this_saver; 2190 return 0; 2191} 2192 2193int 2194remove_scrn_saver(void (*this_saver)(int)) 2195{ 2196 if (current_saver != this_saver) 2197 return EINVAL; 2198 2199 /* 2200 * In order to prevent `current_saver' from being called by 2201 * the timeout routine `scrn_timer()' while we manipulate 2202 * the saver list, we shall set `current_saver' to `none_saver' 2203 * before stopping the current saver, rather than blocking by `splXX()'. 2204 */ 2205 current_saver = none_saver; 2206 if (scrn_blanked > 0) 2207 stop_scrn_saver(this_saver); 2208 2209 if (scrn_blanked > 0) 2210 return EBUSY; /* XXX */ 2211 2212 current_saver = default_saver; 2213 return 0; 2214} 2215 2216static void 2217scrn_saver(void (*saver)(int), int blank) 2218{ 2219 static int busy = FALSE; 2220 2221 if (busy) 2222 return; 2223 busy = TRUE; 2224 (*saver)(blank); 2225 busy = FALSE; 2226} 2227 2228static void 2229stop_scrn_saver(void (*saver)(int)) 2230{ 2231 scrn_saver(saver, FALSE); 2232 run_scrn_saver = FALSE; 2233 /* the screen saver may have chosen not to stop after all... */ 2234 if (scrn_blanked > 0) 2235 return; 2236 2237 mark_all(cur_console); 2238 if (delayed_next_scr) 2239 switch_scr(cur_console, delayed_next_scr - 1); 2240 wakeup((caddr_t)&scrn_blanked); 2241} 2242 2243static int 2244wait_scrn_saver_stop(void) 2245{ 2246 int error = 0; 2247 2248 while (scrn_blanked > 0) { 2249 run_scrn_saver = FALSE; 2250 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); 2251 run_scrn_saver = FALSE; 2252 if (error != ERESTART) 2253 break; 2254 } 2255 return error; 2256} 2257 2258void 2259sc_clear_screen(scr_stat *scp) 2260{ 2261 move_crsr(scp, 0, 0); 2262 scp->cursor_oldpos = scp->cursor_pos; 2263 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2264 scp->xsize * scp->ysize); 2265 mark_all(scp); 2266 remove_cutmarking(scp); 2267} 2268 2269static int 2270switch_scr(scr_stat *scp, u_int next_scr) 2271{ 2272 /* delay switch if actively updating screen */ 2273 if (scrn_blanked > 0 || write_in_progress || blink_in_progress) { 2274 scsplash_stick(FALSE); 2275 run_scrn_saver = FALSE; 2276 delayed_next_scr = next_scr+1; 2277 return 0; 2278 } 2279 2280 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 2281 switch_in_progress = FALSE; 2282 2283 if (next_scr >= MAXCONS || switch_in_progress || 2284 (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { 2285 do_bell(scp, BELL_PITCH, BELL_DURATION); 2286 return EINVAL; 2287 } 2288 2289 /* is the wanted virtual console open ? */ 2290 if (next_scr) { 2291 struct tty *tp = VIRTUAL_TTY(next_scr); 2292 if (!(tp->t_state & TS_ISOPEN)) { 2293 do_bell(scp, BELL_PITCH, BELL_DURATION); 2294 return EINVAL; 2295 } 2296 } 2297 2298 switch_in_progress = TRUE; 2299 old_scp = cur_console; 2300 new_scp = console[next_scr]; 2301 wakeup((caddr_t)&new_scp->smode); 2302 if (new_scp == old_scp) { 2303 switch_in_progress = FALSE; 2304 delayed_next_scr = FALSE; 2305 return 0; 2306 } 2307 2308 /* has controlling process died? */ 2309 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 2310 old_scp->smode.mode = VT_AUTO; 2311 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 2312 new_scp->smode.mode = VT_AUTO; 2313 2314 /* check the modes and switch appropriately */ 2315 if (old_scp->smode.mode == VT_PROCESS) { 2316 old_scp->status |= SWITCH_WAIT_REL; 2317 psignal(old_scp->proc, old_scp->smode.relsig); 2318 } 2319 else { 2320 exchange_scr(); 2321 if (new_scp->smode.mode == VT_PROCESS) { 2322 new_scp->status |= SWITCH_WAIT_ACQ; 2323 psignal(new_scp->proc, new_scp->smode.acqsig); 2324 } 2325 else 2326 switch_in_progress = FALSE; 2327 } 2328 return 0; 2329} 2330 2331static void 2332exchange_scr(void) 2333{ 2334 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 2335 cur_console = new_scp; 2336 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) 2337 set_mode(new_scp); 2338 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 2339 if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) 2340 set_destructive_cursor(new_scp); 2341 if (ISGRAPHSC(old_scp)) 2342 load_palette(new_scp, palette); 2343 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || 2344 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) 2345 shfts = ctls = alts = agrs = metas = accents = 0; 2346 set_border(new_scp, new_scp->border); 2347 update_leds(new_scp->status); 2348 delayed_next_scr = FALSE; 2349 mark_all(new_scp); 2350} 2351 2352static void 2353scan_esc(scr_stat *scp, u_char c) 2354{ 2355 static u_char ansi_col[16] = 2356 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2357 int i, n; 2358 u_short *src, *dst, count; 2359 2360 if (scp->term.esc == 1) { /* seen ESC */ 2361 switch (c) { 2362 2363 case '7': /* Save cursor position */ 2364 scp->saved_xpos = scp->xpos; 2365 scp->saved_ypos = scp->ypos; 2366 break; 2367 2368 case '8': /* Restore saved cursor position */ 2369 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2370 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2371 break; 2372 2373 case '[': /* Start ESC [ sequence */ 2374 scp->term.esc = 2; 2375 scp->term.last_param = -1; 2376 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2377 scp->term.param[i] = 1; 2378 scp->term.num_param = 0; 2379 return; 2380 2381 case 'M': /* Move cursor up 1 line, scroll if at top */ 2382 if (scp->ypos > 0) 2383 move_crsr(scp, scp->xpos, scp->ypos - 1); 2384 else { 2385 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 2386 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 2387 fillw(scp->term.cur_color | scr_map[0x20], 2388 scp->scr_buf, scp->xsize); 2389 mark_all(scp); 2390 } 2391 break; 2392#if notyet 2393 case 'Q': 2394 scp->term.esc = 4; 2395 return; 2396#endif 2397 case 'c': /* Clear screen & home */ 2398 sc_clear_screen(scp); 2399 break; 2400 2401 case '(': /* iso-2022: designate 94 character set to G0 */ 2402 scp->term.esc = 5; 2403 return; 2404 } 2405 } 2406 else if (scp->term.esc == 2) { /* seen ESC [ */ 2407 if (c >= '0' && c <= '9') { 2408 if (scp->term.num_param < MAX_ESC_PAR) { 2409 if (scp->term.last_param != scp->term.num_param) { 2410 scp->term.last_param = scp->term.num_param; 2411 scp->term.param[scp->term.num_param] = 0; 2412 } 2413 else 2414 scp->term.param[scp->term.num_param] *= 10; 2415 scp->term.param[scp->term.num_param] += c - '0'; 2416 return; 2417 } 2418 } 2419 scp->term.num_param = scp->term.last_param + 1; 2420 switch (c) { 2421 2422 case ';': 2423 if (scp->term.num_param < MAX_ESC_PAR) 2424 return; 2425 break; 2426 2427 case '=': 2428 scp->term.esc = 3; 2429 scp->term.last_param = -1; 2430 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2431 scp->term.param[i] = 1; 2432 scp->term.num_param = 0; 2433 return; 2434 2435 case 'A': /* up n rows */ 2436 n = scp->term.param[0]; if (n < 1) n = 1; 2437 move_crsr(scp, scp->xpos, scp->ypos - n); 2438 break; 2439 2440 case 'B': /* down n rows */ 2441 n = scp->term.param[0]; if (n < 1) n = 1; 2442 move_crsr(scp, scp->xpos, scp->ypos + n); 2443 break; 2444 2445 case 'C': /* right n columns */ 2446 n = scp->term.param[0]; if (n < 1) n = 1; 2447 move_crsr(scp, scp->xpos + n, scp->ypos); 2448 break; 2449 2450 case 'D': /* left n columns */ 2451 n = scp->term.param[0]; if (n < 1) n = 1; 2452 move_crsr(scp, scp->xpos - n, scp->ypos); 2453 break; 2454 2455 case 'E': /* cursor to start of line n lines down */ 2456 n = scp->term.param[0]; if (n < 1) n = 1; 2457 move_crsr(scp, 0, scp->ypos + n); 2458 break; 2459 2460 case 'F': /* cursor to start of line n lines up */ 2461 n = scp->term.param[0]; if (n < 1) n = 1; 2462 move_crsr(scp, 0, scp->ypos - n); 2463 break; 2464 2465 case 'f': /* Cursor move */ 2466 case 'H': 2467 if (scp->term.num_param == 0) 2468 move_crsr(scp, 0, 0); 2469 else if (scp->term.num_param == 2) 2470 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2471 break; 2472 2473 case 'J': /* Clear all or part of display */ 2474 if (scp->term.num_param == 0) 2475 n = 0; 2476 else 2477 n = scp->term.param[0]; 2478 switch (n) { 2479 case 0: /* clear form cursor to end of display */ 2480 fillw(scp->term.cur_color | scr_map[0x20], 2481 scp->cursor_pos, 2482 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2483 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2484 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2485 remove_cutmarking(scp); 2486 break; 2487 case 1: /* clear from beginning of display to cursor */ 2488 fillw(scp->term.cur_color | scr_map[0x20], 2489 scp->scr_buf, 2490 scp->cursor_pos - scp->scr_buf); 2491 mark_for_update(scp, 0); 2492 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2493 remove_cutmarking(scp); 2494 break; 2495 case 2: /* clear entire display */ 2496 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2497 scp->xsize * scp->ysize); 2498 mark_all(scp); 2499 remove_cutmarking(scp); 2500 break; 2501 } 2502 break; 2503 2504 case 'K': /* Clear all or part of line */ 2505 if (scp->term.num_param == 0) 2506 n = 0; 2507 else 2508 n = scp->term.param[0]; 2509 switch (n) { 2510 case 0: /* clear form cursor to end of line */ 2511 fillw(scp->term.cur_color | scr_map[0x20], 2512 scp->cursor_pos, 2513 scp->xsize - scp->xpos); 2514 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2515 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2516 scp->xsize - 1 - scp->xpos); 2517 break; 2518 case 1: /* clear from beginning of line to cursor */ 2519 fillw(scp->term.cur_color | scr_map[0x20], 2520 scp->cursor_pos - scp->xpos, 2521 scp->xpos + 1); 2522 mark_for_update(scp, scp->ypos * scp->xsize); 2523 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2524 break; 2525 case 2: /* clear entire line */ 2526 fillw(scp->term.cur_color | scr_map[0x20], 2527 scp->cursor_pos - scp->xpos, 2528 scp->xsize); 2529 mark_for_update(scp, scp->ypos * scp->xsize); 2530 mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); 2531 break; 2532 } 2533 break; 2534 2535 case 'L': /* Insert n lines */ 2536 n = scp->term.param[0]; if (n < 1) n = 1; 2537 if (n > scp->ysize - scp->ypos) 2538 n = scp->ysize - scp->ypos; 2539 src = scp->scr_buf + scp->ypos * scp->xsize; 2540 dst = src + n * scp->xsize; 2541 count = scp->ysize - (scp->ypos + n); 2542 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2543 fillw(scp->term.cur_color | scr_map[0x20], src, 2544 n * scp->xsize); 2545 mark_for_update(scp, scp->ypos * scp->xsize); 2546 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2547 break; 2548 2549 case 'M': /* Delete n lines */ 2550 n = scp->term.param[0]; if (n < 1) n = 1; 2551 if (n > scp->ysize - scp->ypos) 2552 n = scp->ysize - scp->ypos; 2553 dst = scp->scr_buf + scp->ypos * scp->xsize; 2554 src = dst + n * scp->xsize; 2555 count = scp->ysize - (scp->ypos + n); 2556 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2557 src = dst + count * scp->xsize; 2558 fillw(scp->term.cur_color | scr_map[0x20], src, 2559 n * scp->xsize); 2560 mark_for_update(scp, scp->ypos * scp->xsize); 2561 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2562 break; 2563 2564 case 'P': /* Delete n chars */ 2565 n = scp->term.param[0]; if (n < 1) n = 1; 2566 if (n > scp->xsize - scp->xpos) 2567 n = scp->xsize - scp->xpos; 2568 dst = scp->cursor_pos; 2569 src = dst + n; 2570 count = scp->xsize - (scp->xpos + n); 2571 bcopy(src, dst, count * sizeof(u_short)); 2572 src = dst + count; 2573 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2574 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2575 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2576 break; 2577 2578 case '@': /* Insert n chars */ 2579 n = scp->term.param[0]; if (n < 1) n = 1; 2580 if (n > scp->xsize - scp->xpos) 2581 n = scp->xsize - scp->xpos; 2582 src = scp->cursor_pos; 2583 dst = src + n; 2584 count = scp->xsize - (scp->xpos + n); 2585 bcopy(src, dst, count * sizeof(u_short)); 2586 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2587 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2588 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2589 break; 2590 2591 case 'S': /* scroll up n lines */ 2592 n = scp->term.param[0]; if (n < 1) n = 1; 2593 if (n > scp->ysize) 2594 n = scp->ysize; 2595 bcopy(scp->scr_buf + (scp->xsize * n), 2596 scp->scr_buf, 2597 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2598 fillw(scp->term.cur_color | scr_map[0x20], 2599 scp->scr_buf + scp->xsize * (scp->ysize - n), 2600 scp->xsize * n); 2601 mark_all(scp); 2602 break; 2603 2604 case 'T': /* scroll down n lines */ 2605 n = scp->term.param[0]; if (n < 1) n = 1; 2606 if (n > scp->ysize) 2607 n = scp->ysize; 2608 bcopy(scp->scr_buf, 2609 scp->scr_buf + (scp->xsize * n), 2610 scp->xsize * (scp->ysize - n) * 2611 sizeof(u_short)); 2612 fillw(scp->term.cur_color | scr_map[0x20], 2613 scp->scr_buf, scp->xsize * n); 2614 mark_all(scp); 2615 break; 2616 2617 case 'X': /* erase n characters in line */ 2618 n = scp->term.param[0]; if (n < 1) n = 1; 2619 if (n > scp->xsize - scp->xpos) 2620 n = scp->xsize - scp->xpos; 2621 fillw(scp->term.cur_color | scr_map[0x20], 2622 scp->cursor_pos, n); 2623 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2624 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1); 2625 break; 2626 2627 case 'Z': /* move n tabs backwards */ 2628 n = scp->term.param[0]; if (n < 1) n = 1; 2629 if ((i = scp->xpos & 0xf8) == scp->xpos) 2630 i -= 8*n; 2631 else 2632 i -= 8*(n-1); 2633 if (i < 0) 2634 i = 0; 2635 move_crsr(scp, i, scp->ypos); 2636 break; 2637 2638 case '`': /* move cursor to column n */ 2639 n = scp->term.param[0]; if (n < 1) n = 1; 2640 move_crsr(scp, n - 1, scp->ypos); 2641 break; 2642 2643 case 'a': /* move cursor n columns to the right */ 2644 n = scp->term.param[0]; if (n < 1) n = 1; 2645 move_crsr(scp, scp->xpos + n, scp->ypos); 2646 break; 2647 2648 case 'd': /* move cursor to row n */ 2649 n = scp->term.param[0]; if (n < 1) n = 1; 2650 move_crsr(scp, scp->xpos, n - 1); 2651 break; 2652 2653 case 'e': /* move cursor n rows down */ 2654 n = scp->term.param[0]; if (n < 1) n = 1; 2655 move_crsr(scp, scp->xpos, scp->ypos + n); 2656 break; 2657 2658 case 'm': /* change attribute */ 2659 if (scp->term.num_param == 0) { 2660 scp->term.attr_mask = NORMAL_ATTR; 2661 scp->term.cur_attr = 2662 scp->term.cur_color = scp->term.std_color; 2663 break; 2664 } 2665 for (i = 0; i < scp->term.num_param; i++) { 2666 switch (n = scp->term.param[i]) { 2667 case 0: /* back to normal */ 2668 scp->term.attr_mask = NORMAL_ATTR; 2669 scp->term.cur_attr = 2670 scp->term.cur_color = scp->term.std_color; 2671 break; 2672 case 1: /* bold */ 2673 scp->term.attr_mask |= BOLD_ATTR; 2674 scp->term.cur_attr = mask2attr(&scp->term); 2675 break; 2676 case 4: /* underline */ 2677 scp->term.attr_mask |= UNDERLINE_ATTR; 2678 scp->term.cur_attr = mask2attr(&scp->term); 2679 break; 2680 case 5: /* blink */ 2681 scp->term.attr_mask |= BLINK_ATTR; 2682 scp->term.cur_attr = mask2attr(&scp->term); 2683 break; 2684 case 7: /* reverse video */ 2685 scp->term.attr_mask |= REVERSE_ATTR; 2686 scp->term.cur_attr = mask2attr(&scp->term); 2687 break; 2688 case 30: case 31: /* set fg color */ 2689 case 32: case 33: case 34: 2690 case 35: case 36: case 37: 2691 scp->term.attr_mask |= FOREGROUND_CHANGED; 2692 scp->term.cur_color = 2693 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2694 scp->term.cur_attr = mask2attr(&scp->term); 2695 break; 2696 case 40: case 41: /* set bg color */ 2697 case 42: case 43: case 44: 2698 case 45: case 46: case 47: 2699 scp->term.attr_mask |= BACKGROUND_CHANGED; 2700 scp->term.cur_color = 2701 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2702 scp->term.cur_attr = mask2attr(&scp->term); 2703 break; 2704 } 2705 } 2706 break; 2707 2708 case 's': /* Save cursor position */ 2709 scp->saved_xpos = scp->xpos; 2710 scp->saved_ypos = scp->ypos; 2711 break; 2712 2713 case 'u': /* Restore saved cursor position */ 2714 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2715 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2716 break; 2717 2718 case 'x': 2719 if (scp->term.num_param == 0) 2720 n = 0; 2721 else 2722 n = scp->term.param[0]; 2723 switch (n) { 2724 case 0: /* reset attributes */ 2725 scp->term.attr_mask = NORMAL_ATTR; 2726 scp->term.cur_attr = 2727 scp->term.cur_color = scp->term.std_color = 2728 current_default->std_color; 2729 scp->term.rev_color = current_default->rev_color; 2730 break; 2731 case 1: /* set ansi background */ 2732 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2733 scp->term.cur_color = scp->term.std_color = 2734 (scp->term.std_color & 0x0F00) | 2735 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2736 scp->term.cur_attr = mask2attr(&scp->term); 2737 break; 2738 case 2: /* set ansi foreground */ 2739 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2740 scp->term.cur_color = scp->term.std_color = 2741 (scp->term.std_color & 0xF000) | 2742 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2743 scp->term.cur_attr = mask2attr(&scp->term); 2744 break; 2745 case 3: /* set ansi attribute directly */ 2746 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2747 scp->term.cur_color = scp->term.std_color = 2748 (scp->term.param[1]&0xFF)<<8; 2749 scp->term.cur_attr = mask2attr(&scp->term); 2750 break; 2751 case 5: /* set ansi reverse video background */ 2752 scp->term.rev_color = 2753 (scp->term.rev_color & 0x0F00) | 2754 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2755 scp->term.cur_attr = mask2attr(&scp->term); 2756 break; 2757 case 6: /* set ansi reverse video foreground */ 2758 scp->term.rev_color = 2759 (scp->term.rev_color & 0xF000) | 2760 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2761 scp->term.cur_attr = mask2attr(&scp->term); 2762 break; 2763 case 7: /* set ansi reverse video directly */ 2764 scp->term.rev_color = 2765 (scp->term.param[1]&0xFF)<<8; 2766 scp->term.cur_attr = mask2attr(&scp->term); 2767 break; 2768 } 2769 break; 2770 2771 case 'z': /* switch to (virtual) console n */ 2772 if (scp->term.num_param == 1) 2773 switch_scr(scp, scp->term.param[0]); 2774 break; 2775 } 2776 } 2777 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2778 if (c >= '0' && c <= '9') { 2779 if (scp->term.num_param < MAX_ESC_PAR) { 2780 if (scp->term.last_param != scp->term.num_param) { 2781 scp->term.last_param = scp->term.num_param; 2782 scp->term.param[scp->term.num_param] = 0; 2783 } 2784 else 2785 scp->term.param[scp->term.num_param] *= 10; 2786 scp->term.param[scp->term.num_param] += c - '0'; 2787 return; 2788 } 2789 } 2790 scp->term.num_param = scp->term.last_param + 1; 2791 switch (c) { 2792 2793 case ';': 2794 if (scp->term.num_param < MAX_ESC_PAR) 2795 return; 2796 break; 2797 2798 case 'A': /* set display border color */ 2799 if (scp->term.num_param == 1) { 2800 scp->border=scp->term.param[0] & 0xff; 2801 if (scp == cur_console) 2802 set_border(cur_console, scp->border); 2803 } 2804 break; 2805 2806 case 'B': /* set bell pitch and duration */ 2807 if (scp->term.num_param == 2) { 2808 scp->bell_pitch = scp->term.param[0]; 2809 scp->bell_duration = scp->term.param[1]; 2810 } 2811 break; 2812 2813 case 'C': /* set cursor type & shape */ 2814 if (scp->term.num_param == 1) { 2815 if (scp->term.param[0] & 0x01) 2816 sc_flags |= BLINK_CURSOR; 2817 else 2818 sc_flags &= ~BLINK_CURSOR; 2819 if ((scp->term.param[0] & 0x02) 2820 && ISFONTAVAIL(get_adapter(scp)->va_flags)) 2821 sc_flags |= CHAR_CURSOR; 2822 else 2823 sc_flags &= ~CHAR_CURSOR; 2824 } 2825 else if (scp->term.num_param == 2) { 2826 scp->cursor_start = scp->term.param[0] & 0x1F; 2827 scp->cursor_end = scp->term.param[1] & 0x1F; 2828 } 2829 /* 2830 * The cursor shape is global property; all virtual consoles 2831 * are affected. Update the cursor in the current console... 2832 */ 2833 if (!ISGRAPHSC(cur_console)) { 2834 i = spltty(); 2835 remove_cursor_image(cur_console); 2836 if (sc_flags & CHAR_CURSOR) 2837 set_destructive_cursor(cur_console); 2838 draw_cursor_image(cur_console); 2839 splx(i); 2840 } 2841 break; 2842 2843 case 'F': /* set ansi foreground */ 2844 if (scp->term.num_param == 1) { 2845 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2846 scp->term.cur_color = scp->term.std_color = 2847 (scp->term.std_color & 0xF000) 2848 | ((scp->term.param[0] & 0x0F) << 8); 2849 scp->term.cur_attr = mask2attr(&scp->term); 2850 } 2851 break; 2852 2853 case 'G': /* set ansi background */ 2854 if (scp->term.num_param == 1) { 2855 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2856 scp->term.cur_color = scp->term.std_color = 2857 (scp->term.std_color & 0x0F00) 2858 | ((scp->term.param[0] & 0x0F) << 12); 2859 scp->term.cur_attr = mask2attr(&scp->term); 2860 } 2861 break; 2862 2863 case 'H': /* set ansi reverse video foreground */ 2864 if (scp->term.num_param == 1) { 2865 scp->term.rev_color = 2866 (scp->term.rev_color & 0xF000) 2867 | ((scp->term.param[0] & 0x0F) << 8); 2868 scp->term.cur_attr = mask2attr(&scp->term); 2869 } 2870 break; 2871 2872 case 'I': /* set ansi reverse video background */ 2873 if (scp->term.num_param == 1) { 2874 scp->term.rev_color = 2875 (scp->term.rev_color & 0x0F00) 2876 | ((scp->term.param[0] & 0x0F) << 12); 2877 scp->term.cur_attr = mask2attr(&scp->term); 2878 } 2879 break; 2880 } 2881 } 2882#if notyet 2883 else if (scp->term.esc == 4) { /* seen ESC Q */ 2884 /* to be filled */ 2885 } 2886#endif 2887 else if (scp->term.esc == 5) { /* seen ESC ( */ 2888 switch (c) { 2889 case 'B': /* iso-2022: desginate ASCII into G0 */ 2890 break; 2891 /* other items to be filled */ 2892 default: 2893 break; 2894 } 2895 } 2896 scp->term.esc = 0; 2897} 2898 2899static void 2900ansi_put(scr_stat *scp, u_char *buf, int len) 2901{ 2902 u_char *ptr = buf; 2903 2904 /* make screensaver happy */ 2905 if (!sticky_splash && scp == cur_console) 2906 run_scrn_saver = FALSE; 2907 2908 write_in_progress++; 2909outloop: 2910 if (scp->term.esc) { 2911 scan_esc(scp, *ptr++); 2912 len--; 2913 } 2914 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2915 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2916 u_short cur_attr = scp->term.cur_attr; 2917 u_short *cursor_pos = scp->cursor_pos; 2918 do { 2919 /* 2920 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2921 * pointers in the following to volatile should have no effect, 2922 * but in fact speeds up this inner loop from 26 to 18 cycles 2923 * (+ cache misses) on i486's. 2924 */ 2925#define UCVP(ucp) ((u_char volatile *)(ucp)) 2926 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2927 ptr++; 2928 cnt--; 2929 } while (cnt && PRINTABLE(*ptr)); 2930 len -= (cursor_pos - scp->cursor_pos); 2931 scp->xpos += (cursor_pos - scp->cursor_pos); 2932 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2933 mark_for_update(scp, cursor_pos - scp->scr_buf); 2934 scp->cursor_pos = cursor_pos; 2935 if (scp->xpos >= scp->xsize) { 2936 scp->xpos = 0; 2937 scp->ypos++; 2938 } 2939 } 2940 else { 2941 switch(*ptr) { 2942 case 0x07: 2943 do_bell(scp, scp->bell_pitch, scp->bell_duration); 2944 break; 2945 2946 case 0x08: /* non-destructive backspace */ 2947 if (scp->cursor_pos > scp->scr_buf) { 2948 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2949 scp->cursor_pos--; 2950 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2951 if (scp->xpos > 0) 2952 scp->xpos--; 2953 else { 2954 scp->xpos += scp->xsize - 1; 2955 scp->ypos--; 2956 } 2957 } 2958 break; 2959 2960 case 0x09: /* non-destructive tab */ 2961 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2962 scp->cursor_pos += (8 - scp->xpos % 8u); 2963 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2964 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 2965 scp->xpos = 0; 2966 scp->ypos++; 2967 } 2968 break; 2969 2970 case 0x0a: /* newline, same pos */ 2971 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2972 scp->cursor_pos += scp->xsize; 2973 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2974 scp->ypos++; 2975 break; 2976 2977 case 0x0c: /* form feed, clears screen */ 2978 sc_clear_screen(scp); 2979 break; 2980 2981 case 0x0d: /* return, return to pos 0 */ 2982 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2983 scp->cursor_pos -= scp->xpos; 2984 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2985 scp->xpos = 0; 2986 break; 2987 2988 case 0x1b: /* start escape sequence */ 2989 scp->term.esc = 1; 2990 scp->term.num_param = 0; 2991 break; 2992 } 2993 ptr++; len--; 2994 } 2995 /* do we have to scroll ?? */ 2996 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 2997 remove_cutmarking(scp); 2998 if (scp->history != NULL) { 2999 bcopy(scp->scr_buf, scp->history_head, 3000 scp->xsize * sizeof(u_short)); 3001 scp->history_head += scp->xsize; 3002 if (scp->history_head + scp->xsize > 3003 scp->history + scp->history_size) 3004 scp->history_head = scp->history; 3005 } 3006 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 3007 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 3008 fillw(scp->term.cur_color | scr_map[0x20], 3009 scp->scr_buf + scp->xsize * (scp->ysize - 1), 3010 scp->xsize); 3011 scp->cursor_pos -= scp->xsize; 3012 scp->ypos--; 3013 mark_all(scp); 3014 } 3015 if (len) 3016 goto outloop; 3017 write_in_progress--; 3018 if (delayed_next_scr) 3019 switch_scr(scp, delayed_next_scr - 1); 3020} 3021 3022static void 3023scinit(void) 3024{ 3025 int col; 3026 int row; 3027 u_int i; 3028 3029 if (init_done != COLD) 3030 return; 3031 init_done = WARM; 3032 3033 /* extract the hardware cursor location and move it out of the way */ 3034 (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row); 3035 (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1); 3036 3037 /* set up the first console */ 3038 current_default = &user_default; 3039 console[0] = &main_console; 3040 init_scp(console[0]); 3041 cur_console = console[0]; 3042 3043 /* copy screen to temporary buffer */ 3044 if (ISTEXTSC(console[0])) 3045 generic_bcopy((ushort *)(get_adapter(console[0])->va_window), sc_buffer, 3046 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 3047 3048 console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos 3049 = sc_buffer; 3050 if (col >= console[0]->xsize) 3051 col = 0; 3052 if (row >= console[0]->ysize) 3053 row = console[0]->ysize - 1; 3054 console[0]->xpos = col; 3055 console[0]->ypos = row; 3056 console[0]->cursor_pos = console[0]->cursor_oldpos = 3057 sc_buffer + row*console[0]->xsize + col; 3058 console[0]->cursor_saveunder = *console[0]->cursor_pos; 3059 for (i=1; i<MAXCONS; i++) 3060 console[i] = NULL; 3061 kernel_console.esc = 0; 3062 kernel_console.attr_mask = NORMAL_ATTR; 3063 kernel_console.cur_attr = 3064 kernel_console.cur_color = kernel_console.std_color = 3065 kernel_default.std_color; 3066 kernel_console.rev_color = kernel_default.rev_color; 3067 3068 /* initialize mapscrn arrays to a one to one map */ 3069 for (i=0; i<sizeof(scr_map); i++) { 3070 scr_map[i] = scr_rmap[i] = i; 3071 } 3072 3073 /* Save font and palette */ 3074 if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) { 3075 if (fonts_loaded & FONT_16) { 3076 copy_font(cur_console, LOAD, 16, font_16); 3077 } else { 3078 copy_font(cur_console, SAVE, 16, font_16); 3079 fonts_loaded = FONT_16; 3080 set_destructive_cursor(cur_console); 3081 } 3082 /* 3083 * FONT KLUDGE 3084 * Always use the font page #0. XXX 3085 */ 3086 (*biosvidsw.show_font)(cur_console->adp, 0); 3087 } 3088 save_palette(cur_console, palette); 3089 3090#ifdef SC_SPLASH_SCREEN 3091 /* put up the splash. */ 3092 scsplash_init(cur_console); 3093#endif 3094} 3095 3096static void 3097scshutdown(int howto, void *arg) 3098{ 3099 scsplash_stick(FALSE); 3100 run_scrn_saver = FALSE; 3101 if (!cold && cur_console->smode.mode == VT_AUTO 3102 && console[0]->smode.mode == VT_AUTO) 3103 switch_scr(cur_console, 0); 3104 shutdown_in_progress = TRUE; 3105} 3106 3107int 3108sc_clean_up(scr_stat *scp) 3109{ 3110 int error; 3111 3112 if ((error = wait_scrn_saver_stop())) 3113 return error; 3114 scp->status &= ~MOUSE_VISIBLE; 3115 remove_cutmarking(scp); 3116 return 0; 3117} 3118 3119void 3120sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) 3121{ 3122 if (scp->scr_buf) 3123 free(scp->scr_buf, M_DEVBUF); 3124 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 3125 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3126 3127 if (clear) { 3128 /* clear the screen and move the text cursor to the top-left position */ 3129 sc_clear_screen(scp); 3130 } else { 3131 /* retain the current cursor position, but adjust pointers */ 3132 move_crsr(scp, scp->xpos, scp->ypos); 3133 scp->cursor_oldpos = scp->cursor_pos; 3134 } 3135 3136 /* move the mouse cursor at the center of the screen */ 3137 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); 3138} 3139 3140void 3141sc_alloc_cut_buffer(scr_stat *scp, int wait) 3142{ 3143 if ((cut_buffer == NULL) 3144 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 3145 if (cut_buffer != NULL) 3146 free(cut_buffer, M_DEVBUF); 3147 cut_buffer_size = scp->xsize * scp->ysize + 1; 3148 cut_buffer = (u_char *)malloc(cut_buffer_size, 3149 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3150 if (cut_buffer != NULL) 3151 cut_buffer[0] = '\0'; 3152 } 3153} 3154 3155void 3156sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) 3157{ 3158 u_short *usp; 3159 3160 if (lines < scp->ysize) 3161 lines = scp->ysize; 3162 3163 usp = scp->history; 3164 scp->history = NULL; 3165 if (usp != NULL) { 3166 free(usp, M_DEVBUF); 3167 if (extra > 0) 3168 extra_history_size += extra; 3169 } 3170 3171 scp->history_size = lines * scp->xsize; 3172 if (lines > imax(sc_history_size, scp->ysize)) 3173 extra_history_size -= lines - imax(sc_history_size, scp->ysize); 3174 usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 3175 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3176 if (usp != NULL) 3177 bzero(usp, scp->history_size * sizeof(u_short)); 3178 scp->history_head = scp->history_pos = usp; 3179 scp->history = usp; 3180} 3181 3182static scr_stat 3183*alloc_scp() 3184{ 3185 scr_stat *scp; 3186 3187 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3188 init_scp(scp); 3189 sc_alloc_scr_buffer(scp, TRUE, TRUE); 3190 if (ISMOUSEAVAIL(get_adapter(scp)->va_flags)) 3191 sc_alloc_cut_buffer(scp, TRUE); 3192 sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); 3193/* SOS 3194 if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE) 3195 set_mode(scp); 3196*/ 3197 sc_clear_screen(scp); 3198 scp->cursor_saveunder = *scp->cursor_pos; 3199 return scp; 3200} 3201 3202static void 3203init_scp(scr_stat *scp) 3204{ 3205 video_info_t info; 3206 3207 scp->adp = V_ADP_PRIMARY; 3208 (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info); 3209 3210 scp->status = 0; 3211 scp->mode = scp->initial_mode = initial_video_mode; 3212 scp->scr_buf = NULL; 3213 if (info.vi_flags & V_INFO_GRAPHICS) { 3214 scp->status |= GRAPHICS_MODE; 3215 scp->xpixel = info.vi_width; 3216 scp->ypixel = info.vi_height; 3217 scp->xsize = info.vi_width/8; 3218 scp->ysize = info.vi_height/info.vi_cheight; 3219 scp->font_size = FONT_NONE; 3220 } else { 3221 scp->xsize = info.vi_width; 3222 scp->ysize = info.vi_height; 3223 scp->xpixel = scp->xsize*8; 3224 scp->ypixel = scp->ysize*info.vi_cheight; 3225 scp->font_size = info.vi_cheight; 3226 } 3227 scp->xoff = scp->yoff = 0; 3228 scp->xpos = scp->ypos = 0; 3229 scp->saved_xpos = scp->saved_ypos = -1; 3230 scp->start = scp->xsize * scp->ysize; 3231 scp->end = 0; 3232 scp->term.esc = 0; 3233 scp->term.attr_mask = NORMAL_ATTR; 3234 scp->term.cur_attr = 3235 scp->term.cur_color = scp->term.std_color = 3236 current_default->std_color; 3237 scp->term.rev_color = current_default->rev_color; 3238 scp->border = BG_BLACK; 3239 scp->cursor_start = *(u_int8_t *)pa_to_va(0x461); 3240 scp->cursor_end = *(u_int8_t *)pa_to_va(0x460); 3241 scp->mouse_xpos = scp->xsize*8/2; 3242 scp->mouse_ypos = scp->ysize*scp->font_size/2; 3243 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3244 scp->mouse_signal = 0; 3245 scp->mouse_pid = 0; 3246 scp->mouse_proc = NULL; 3247 scp->bell_pitch = BELL_PITCH; 3248 scp->bell_duration = BELL_DURATION; 3249 scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 3250 scp->status |= CURSOR_ENABLED; 3251 scp->pid = 0; 3252 scp->proc = NULL; 3253 scp->smode.mode = VT_AUTO; 3254 scp->history_head = scp->history_pos = scp->history = NULL; 3255 scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; 3256} 3257 3258static u_char 3259*get_fstr(u_int c, u_int *len) 3260{ 3261 u_int i; 3262 3263 if (!(c & FKEY)) 3264 return(NULL); 3265 i = (c & 0xFF) - F_FN; 3266 if (i > n_fkey_tab) 3267 return(NULL); 3268 *len = fkey_tab[i].len; 3269 return(fkey_tab[i].str); 3270} 3271 3272static void 3273history_to_screen(scr_stat *scp) 3274{ 3275 int i; 3276 3277 for (i=0; i<scp->ysize; i++) 3278 bcopy(scp->history + (((scp->history_pos - scp->history) + 3279 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 3280 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 3281 scp->xsize * sizeof(u_short)); 3282 mark_all(scp); 3283} 3284 3285static int 3286history_up_line(scr_stat *scp) 3287{ 3288 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 3289 scp->history_head) { 3290 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 3291 history_to_screen(scp); 3292 return 0; 3293 } 3294 else 3295 return -1; 3296} 3297 3298static int 3299history_down_line(scr_stat *scp) 3300{ 3301 if (scp->history_pos != scp->history_head) { 3302 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 3303 history_to_screen(scp); 3304 return 0; 3305 } 3306 else 3307 return -1; 3308} 3309 3310/* 3311 * scgetc(flags) - get character from keyboard. 3312 * If flags & SCGETC_CN, then avoid harmful side effects. 3313 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3314 * return NOKEY if there is nothing there. 3315 */ 3316static u_int 3317scgetc(u_int flags) 3318{ 3319 struct key_t *key; 3320 u_char scancode, keycode; 3321 u_int state, action; 3322 int c; 3323 static u_char esc_flag = 0, compose = 0; 3324 static u_int chr = 0; 3325 3326next_code: 3327 /* first see if there is something in the keyboard port */ 3328 if (flags & SCGETC_NONBLOCK) { 3329 c = read_kbd_data_no_wait(sc_kbdc); 3330 if (c == -1) 3331 return(NOKEY); 3332 } else { 3333 do { 3334 c = read_kbd_data(sc_kbdc); 3335 } while(c == -1); 3336 } 3337 scancode = (u_char)c; 3338 3339 /* make screensaver happy */ 3340 if (!(scancode & 0x80)) { 3341 scsplash_stick(FALSE); 3342 run_scrn_saver = FALSE; 3343 } 3344 3345 if (!(flags & SCGETC_CN)) { 3346 /* do the /dev/random device a favour */ 3347 add_keyboard_randomness(scancode); 3348 3349 if (cur_console->status & KBD_RAW_MODE) 3350 return scancode; 3351 } 3352 3353 keycode = scancode & 0x7F; 3354 switch (esc_flag) { 3355 case 0x00: /* normal scancode */ 3356 switch(scancode) { 3357 case 0xB8: /* left alt (compose key) */ 3358 if (compose) { 3359 compose = 0; 3360 if (chr > 255) { 3361 do_bell(cur_console, 3362 BELL_PITCH, BELL_DURATION); 3363 chr = 0; 3364 } 3365 } 3366 break; 3367 case 0x38: 3368 if (!compose) { 3369 compose = 1; 3370 chr = 0; 3371 } 3372 break; 3373 case 0xE0: 3374 case 0xE1: 3375 esc_flag = scancode; 3376 goto next_code; 3377 } 3378 break; 3379 case 0xE0: /* 0xE0 prefix */ 3380 esc_flag = 0; 3381 switch (keycode) { 3382 case 0x1C: /* right enter key */ 3383 keycode = 0x59; 3384 break; 3385 case 0x1D: /* right ctrl key */ 3386 keycode = 0x5A; 3387 break; 3388 case 0x35: /* keypad divide key */ 3389 keycode = 0x5B; 3390 break; 3391 case 0x37: /* print scrn key */ 3392 keycode = 0x5C; 3393 break; 3394 case 0x38: /* right alt key (alt gr) */ 3395 keycode = 0x5D; 3396 break; 3397 case 0x47: /* grey home key */ 3398 keycode = 0x5E; 3399 break; 3400 case 0x48: /* grey up arrow key */ 3401 keycode = 0x5F; 3402 break; 3403 case 0x49: /* grey page up key */ 3404 keycode = 0x60; 3405 break; 3406 case 0x4B: /* grey left arrow key */ 3407 keycode = 0x61; 3408 break; 3409 case 0x4D: /* grey right arrow key */ 3410 keycode = 0x62; 3411 break; 3412 case 0x4F: /* grey end key */ 3413 keycode = 0x63; 3414 break; 3415 case 0x50: /* grey down arrow key */ 3416 keycode = 0x64; 3417 break; 3418 case 0x51: /* grey page down key */ 3419 keycode = 0x65; 3420 break; 3421 case 0x52: /* grey insert key */ 3422 keycode = 0x66; 3423 break; 3424 case 0x53: /* grey delete key */ 3425 keycode = 0x67; 3426 break; 3427 3428 /* the following 3 are only used on the MS "Natural" keyboard */ 3429 case 0x5b: /* left Window key */ 3430 keycode = 0x69; 3431 break; 3432 case 0x5c: /* right Window key */ 3433 keycode = 0x6a; 3434 break; 3435 case 0x5d: /* menu key */ 3436 keycode = 0x6b; 3437 break; 3438 default: /* ignore everything else */ 3439 goto next_code; 3440 } 3441 break; 3442 case 0xE1: /* 0xE1 prefix */ 3443 esc_flag = 0; 3444 if (keycode == 0x1D) 3445 esc_flag = 0x1D; 3446 goto next_code; 3447 /* NOT REACHED */ 3448 case 0x1D: /* pause / break */ 3449 esc_flag = 0; 3450 if (keycode != 0x45) 3451 goto next_code; 3452 keycode = 0x68; 3453 break; 3454 } 3455 3456 if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE)) 3457 return (keycode | (scancode & 0x80)); 3458 3459 /* if scroll-lock pressed allow history browsing */ 3460 if (cur_console->history && cur_console->status & SLKED) { 3461 int i; 3462 3463 cur_console->status &= ~CURSOR_ENABLED; 3464 if (!(cur_console->status & BUFFER_SAVED)) { 3465 cur_console->status |= BUFFER_SAVED; 3466 cur_console->history_save = cur_console->history_head; 3467 3468 /* copy screen into top of history buffer */ 3469 for (i=0; i<cur_console->ysize; i++) { 3470 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 3471 cur_console->history_head, 3472 cur_console->xsize * sizeof(u_short)); 3473 cur_console->history_head += cur_console->xsize; 3474 if (cur_console->history_head + cur_console->xsize > 3475 cur_console->history + cur_console->history_size) 3476 cur_console->history_head=cur_console->history; 3477 } 3478 cur_console->history_pos = cur_console->history_head; 3479 history_to_screen(cur_console); 3480 } 3481 switch (scancode) { 3482 case 0x47: /* home key */ 3483 cur_console->history_pos = cur_console->history_head; 3484 history_to_screen(cur_console); 3485 goto next_code; 3486 3487 case 0x4F: /* end key */ 3488 cur_console->history_pos = 3489 WRAPHIST(cur_console, cur_console->history_head, 3490 cur_console->xsize*cur_console->ysize); 3491 history_to_screen(cur_console); 3492 goto next_code; 3493 3494 case 0x48: /* up arrow key */ 3495 if (history_up_line(cur_console)) 3496 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3497 goto next_code; 3498 3499 case 0x50: /* down arrow key */ 3500 if (history_down_line(cur_console)) 3501 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3502 goto next_code; 3503 3504 case 0x49: /* page up key */ 3505 for (i=0; i<cur_console->ysize; i++) 3506 if (history_up_line(cur_console)) { 3507 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3508 break; 3509 } 3510 goto next_code; 3511 3512 case 0x51: /* page down key */ 3513 for (i=0; i<cur_console->ysize; i++) 3514 if (history_down_line(cur_console)) { 3515 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3516 break; 3517 } 3518 goto next_code; 3519 } 3520 } 3521 3522 if (compose) { 3523 switch (scancode) { 3524 /* key pressed process it */ 3525 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 3526 chr = (scancode - 0x40) + chr*10; 3527 goto next_code; 3528 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 3529 chr = (scancode - 0x47) + chr*10; 3530 goto next_code; 3531 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 3532 chr = (scancode - 0x4E) + chr*10; 3533 goto next_code; 3534 case 0x52: /* keypad 0 */ 3535 chr *= 10; 3536 goto next_code; 3537 3538 /* key release, no interest here */ 3539 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 3540 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 3541 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 3542 case 0xD2: /* keypad 0 */ 3543 goto next_code; 3544 3545 case 0x38: /* left alt key */ 3546 break; 3547 default: 3548 if (chr) { 3549 compose = chr = 0; 3550 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3551 goto next_code; 3552 } 3553 break; 3554 } 3555 } 3556 3557 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 3558 if ((!agrs && (cur_console->status & ALKED)) 3559 || (agrs && !(cur_console->status & ALKED))) 3560 keycode += ALTGR_OFFSET; 3561 key = &key_map.key[keycode]; 3562 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 3563 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 3564 state ^= 1; 3565 3566 /* Check for make/break */ 3567 action = key->map[state]; 3568 if (scancode & 0x80) { /* key released */ 3569 if (key->spcl & (0x80>>state)) { 3570 switch (action) { 3571 case LSH: 3572 shfts &= ~1; 3573 break; 3574 case RSH: 3575 shfts &= ~2; 3576 break; 3577 case LCTR: 3578 ctls &= ~1; 3579 break; 3580 case RCTR: 3581 ctls &= ~2; 3582 break; 3583 case LALT: 3584 alts &= ~1; 3585 break; 3586 case RALT: 3587 alts &= ~2; 3588 break; 3589 case NLK: 3590 nlkcnt = 0; 3591 break; 3592 case CLK: 3593 clkcnt = 0; 3594 break; 3595 case SLK: 3596 slkcnt = 0; 3597 break; 3598 case ASH: 3599 agrs = 0; 3600 break; 3601 case ALK: 3602 alkcnt = 0; 3603 break; 3604 case META: 3605 metas = 0; 3606 break; 3607 } 3608 } 3609 if (chr && !compose) { 3610 action = chr; 3611 chr = 0; 3612 return(action); 3613 } 3614 } else { 3615 /* key pressed */ 3616 if (key->spcl & (0x80>>state)) { 3617 switch (action) { 3618 /* LOCKING KEYS */ 3619 case NLK: 3620 if (!nlkcnt) { 3621 nlkcnt++; 3622 if (cur_console->status & NLKED) 3623 cur_console->status &= ~NLKED; 3624 else 3625 cur_console->status |= NLKED; 3626 update_leds(cur_console->status); 3627 } 3628 break; 3629 case CLK: 3630 if (!clkcnt) { 3631 clkcnt++; 3632 if (cur_console->status & CLKED) 3633 cur_console->status &= ~CLKED; 3634 else 3635 cur_console->status |= CLKED; 3636 update_leds(cur_console->status); 3637 } 3638 break; 3639 case SLK: 3640 if (!slkcnt) { 3641 slkcnt++; 3642 if (cur_console->status & SLKED) { 3643 cur_console->status &= ~SLKED; 3644 if (cur_console->status & BUFFER_SAVED){ 3645 int i; 3646 u_short *ptr = cur_console->history_save; 3647 3648 for (i=0; i<cur_console->ysize; i++) { 3649 bcopy(ptr, 3650 cur_console->scr_buf + 3651 (cur_console->xsize*i), 3652 cur_console->xsize * sizeof(u_short)); 3653 ptr += cur_console->xsize; 3654 if (ptr + cur_console->xsize > 3655 cur_console->history + 3656 cur_console->history_size) 3657 ptr = cur_console->history; 3658 } 3659 cur_console->status &= ~BUFFER_SAVED; 3660 cur_console->history_head=cur_console->history_save; 3661 cur_console->status |= CURSOR_ENABLED; 3662 mark_all(cur_console); 3663 } 3664 scstart(VIRTUAL_TTY(get_scr_num())); 3665 } 3666 else 3667 cur_console->status |= SLKED; 3668 update_leds(cur_console->status); 3669 } 3670 break; 3671 case ALK: 3672 if (!alkcnt) { 3673 alkcnt++; 3674 if (cur_console->status & ALKED) 3675 cur_console->status &= ~ALKED; 3676 else 3677 cur_console->status |= ALKED; 3678 update_leds(cur_console->status); 3679 } 3680 break; 3681 3682 /* NON-LOCKING KEYS */ 3683 case NOP: 3684 break; 3685 case SPSC: 3686 /* force activatation/deactivation of the screen saver */ 3687 accents = 0; 3688 if (scrn_blanked <= 0) { 3689 run_scrn_saver = TRUE; 3690 scrn_time_stamp -= scrn_blank_time; 3691 } 3692#ifdef SC_SPLASH_SCREEN 3693 if (cold) { 3694 /* 3695 * While devices are being probed, the screen saver need 3696 * to be invoked explictly. XXX 3697 */ 3698 if (scrn_blanked > 0) { 3699 scsplash_stick(FALSE); 3700 stop_scrn_saver(current_saver); 3701 } else { 3702 if (!ISGRAPHSC(cur_console)) { 3703 scsplash_stick(TRUE); 3704 scrn_saver(current_saver, TRUE); 3705 } 3706 } 3707 } 3708#endif 3709 break; 3710 case RBT: 3711#ifndef SC_DISABLE_REBOOT 3712 accents = 0; 3713 shutdown_nice(); 3714#endif 3715 break; 3716 case SUSP: 3717#if NAPM > 0 3718 accents = 0; 3719 apm_suspend(PMST_SUSPEND); 3720#endif 3721 break; 3722 3723 case STBY: 3724#if NAPM > 0 3725 accents = 0; 3726 apm_suspend(PMST_STANDBY); 3727#endif 3728 break; 3729 3730 case DBG: 3731#ifdef DDB /* try to switch to console 0 */ 3732 accents = 0; 3733 /* 3734 * TRY to make sure the screen saver is stopped, 3735 * and the screen is updated before switching to 3736 * the vty0. 3737 */ 3738 scrn_timer((void *)FALSE); 3739 if (cur_console->smode.mode == VT_AUTO && 3740 console[0]->smode.mode == VT_AUTO) 3741 switch_scr(cur_console, 0); 3742 Debugger("manual escape to debugger"); 3743#else 3744 printf("No debugger in kernel\n"); 3745#endif 3746 break; 3747 case LSH: 3748 shfts |= 1; 3749 break; 3750 case RSH: 3751 shfts |= 2; 3752 break; 3753 case LCTR: 3754 ctls |= 1; 3755 break; 3756 case RCTR: 3757 ctls |= 2; 3758 break; 3759 case LALT: 3760 alts |= 1; 3761 break; 3762 case RALT: 3763 alts |= 2; 3764 break; 3765 case ASH: 3766 agrs = 1; 3767 break; 3768 case META: 3769 metas = 1; 3770 break; 3771 case NEXT: 3772 { 3773 int next, this = get_scr_num(); 3774 accents = 0; 3775 for (next = this+1; next != this; next = (next+1)%MAXCONS) { 3776 struct tty *tp = VIRTUAL_TTY(next); 3777 if (tp->t_state & TS_ISOPEN) { 3778 switch_scr(cur_console, next); 3779 break; 3780 } 3781 } 3782 } 3783 break; 3784 case BTAB: 3785 accents = 0; 3786 return(BKEY); 3787 default: 3788 if (action >= F_ACC && action <= L_ACC) { 3789 /* turn it into an index */ 3790 action -= F_ACC - 1; 3791 if ((action > accent_map.n_accs) 3792 || (accent_map.acc[action - 1].accchar == 0)) { 3793 /* 3794 * The index is out of range or pointing to an 3795 * empty entry. 3796 */ 3797 accents = 0; 3798 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3799 } 3800 /* 3801 * If the same accent key has been hit twice, 3802 * produce the accent char itself. 3803 */ 3804 if (action == accents) { 3805 action = accent_map.acc[accents - 1].accchar; 3806 accents = 0; 3807 if (metas) 3808 action |= MKEY; 3809 return (action); 3810 } 3811 /* remember the index and wait for the next key stroke */ 3812 accents = action; 3813 break; 3814 } 3815 if (accents > 0) { 3816 accents = 0; 3817 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3818 } 3819 if (action >= F_SCR && action <= L_SCR) { 3820 switch_scr(cur_console, action - F_SCR); 3821 break; 3822 } 3823 if (action >= F_FN && action <= L_FN) 3824 action |= FKEY; 3825 return(action); 3826 } 3827 } 3828 else { 3829 if (accents) { 3830 struct acc_t *acc; 3831 int i; 3832 3833 acc = &accent_map.acc[accents - 1]; 3834 accents = 0; 3835 /* 3836 * If the accent key is followed by the space key, 3837 * produce the accent char itself. 3838 */ 3839 if (action == ' ') { 3840 action = acc->accchar; 3841 if (metas) 3842 action |= MKEY; 3843 return (action); 3844 } 3845 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 3846 if (acc->map[i][0] == 0) /* end of the map entry */ 3847 break; 3848 if (acc->map[i][0] == action) { 3849 action = acc->map[i][1]; 3850 if (metas) 3851 action |= MKEY; 3852 return (action); 3853 } 3854 } 3855 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3856 goto next_code; 3857 } 3858 if (metas) 3859 action |= MKEY; 3860 return(action); 3861 } 3862 } 3863 goto next_code; 3864} 3865 3866int 3867scmmap(dev_t dev, vm_offset_t offset, int nprot) 3868{ 3869 if (offset > 0x20000 - PAGE_SIZE) 3870 return -1; 3871 return i386_btop((VIDEOMEM + offset)); 3872} 3873 3874/* 3875 * Calculate hardware attributes word using logical attributes mask and 3876 * hardware colors 3877 */ 3878 3879static int 3880mask2attr(struct term_stat *term) 3881{ 3882 int attr, mask = term->attr_mask; 3883 3884 if (mask & REVERSE_ATTR) { 3885 attr = ((mask & FOREGROUND_CHANGED) ? 3886 ((term->cur_color & 0xF000) >> 4) : 3887 (term->rev_color & 0x0F00)) | 3888 ((mask & BACKGROUND_CHANGED) ? 3889 ((term->cur_color & 0x0F00) << 4) : 3890 (term->rev_color & 0xF000)); 3891 } else 3892 attr = term->cur_color; 3893 3894 /* XXX: underline mapping for Hercules adapter can be better */ 3895 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3896 attr ^= 0x0800; 3897 if (mask & BLINK_ATTR) 3898 attr ^= 0x8000; 3899 3900 return attr; 3901} 3902 3903static void 3904set_keyboard(int command, int data) 3905{ 3906 int s; 3907 3908 if (sc_kbdc == NULL) 3909 return; 3910 3911 /* prevent the timeout routine from polling the keyboard */ 3912 if (!kbdc_lock(sc_kbdc, TRUE)) 3913 return; 3914 3915 /* disable the keyboard and mouse interrupt */ 3916 s = spltty(); 3917#if 0 3918 c = get_controller_command_byte(sc_kbdc); 3919 if ((c == -1) 3920 || !set_controller_command_byte(sc_kbdc, 3921 kbdc_get_device_mask(sc_kbdc), 3922 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 3923 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 3924 /* CONTROLLER ERROR */ 3925 kbdc_lock(sc_kbdc, FALSE); 3926 splx(s); 3927 return; 3928 } 3929 /* 3930 * Now that the keyboard controller is told not to generate 3931 * the keyboard and mouse interrupts, call `splx()' to allow 3932 * the other tty interrupts. The clock interrupt may also occur, 3933 * but the timeout routine (`scrn_timer()') will be blocked 3934 * by the lock flag set via `kbdc_lock()' 3935 */ 3936 splx(s); 3937#endif 3938 3939 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) 3940 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); 3941 3942#if 0 3943 /* restore the interrupts */ 3944 if (!set_controller_command_byte(sc_kbdc, 3945 kbdc_get_device_mask(sc_kbdc), 3946 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 3947 /* CONTROLLER ERROR */ 3948 } 3949#else 3950 splx(s); 3951#endif 3952 kbdc_lock(sc_kbdc, FALSE); 3953} 3954 3955static void 3956update_leds(int which) 3957{ 3958 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 3959 3960 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 3961 if (key_map.n_keys > ALTGR_OFFSET) { 3962 if (which & ALKED) 3963 which |= CLKED; 3964 else 3965 which &= ~CLKED; 3966 } 3967 3968 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); 3969} 3970 3971int 3972set_mode(scr_stat *scp) 3973{ 3974 video_info_t info; 3975 video_adapter_t *adp; 3976 3977 /* reject unsupported mode */ 3978 if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) 3979 return 1; 3980 3981 /* if this vty is not currently showing, do nothing */ 3982 if (scp != cur_console) 3983 return 0; 3984 3985 /* setup video hardware for the given mode */ 3986 adp = get_adapter(scp); 3987 (*biosvidsw.set_mode)(scp->adp, scp->mode); 3988 Crtat = (u_short *)adp->va_window; 3989 3990 if (!(scp->status & GRAPHICS_MODE)) { 3991 /* load appropriate font */ 3992 if (!(scp->status & PIXEL_MODE) 3993 && ISFONTAVAIL(get_adapter(scp)->va_flags)) { 3994 if (scp->font_size < 14) { 3995 if (fonts_loaded & FONT_8) 3996 copy_font(scp, LOAD, 8, font_8); 3997 } else if (scp->font_size >= 16) { 3998 if (fonts_loaded & FONT_16) 3999 copy_font(scp, LOAD, 16, font_16); 4000 } else { 4001 if (fonts_loaded & FONT_14) 4002 copy_font(scp, LOAD, 14, font_14); 4003 } 4004 /* 4005 * FONT KLUDGE: 4006 * This is an interim kludge to display correct font. 4007 * Always use the font page #0 on the video plane 2. 4008 * Somehow we cannot show the font in other font pages on 4009 * some video cards... XXX 4010 */ 4011 (*biosvidsw.show_font)(scp->adp, 0); 4012 } 4013 mark_all(scp); 4014 } 4015 4016 if (scp->status & PIXEL_MODE) 4017 generic_bzero((u_char *)(adp->va_window), scp->xpixel*scp->ypixel/8); 4018 set_border(scp, scp->border); 4019 4020 /* move hardware cursor out of the way */ 4021 (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); 4022 4023 return 0; 4024} 4025 4026void 4027set_border(scr_stat *scp, int color) 4028{ 4029 u_char *p; 4030 int xoff; 4031 int yoff; 4032 int xlen; 4033 int ylen; 4034 int i; 4035 4036 (*biosvidsw.set_border)(scp->adp, color); 4037 4038 if (scp->status & PIXEL_MODE) { 4039 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4040 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4041 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4042 outw(GDCIDX, 0xff08); /* bit mask */ 4043 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 4044 p = (u_char *)(get_adapter(scp)->va_window); 4045 xoff = scp->xoff; 4046 yoff = scp->yoff*scp->font_size; 4047 xlen = scp->xpixel/8; 4048 ylen = scp->ysize*scp->font_size; 4049 if (yoff > 0) { 4050 generic_bzero(p, xlen*yoff); 4051 generic_bzero(p + xlen*(yoff + ylen), 4052 xlen*scp->ypixel - xlen*(yoff + ylen)); 4053 } 4054 if (xoff > 0) { 4055 for (i = 0; i < ylen; ++i) { 4056 generic_bzero(p + xlen*(yoff + i), xoff); 4057 generic_bzero(p + xlen*(yoff + i) + xoff + scp->xsize, 4058 xlen - xoff - scp->xsize); 4059 } 4060 } 4061 outw(GDCIDX, 0x0000); /* set/reset */ 4062 outw(GDCIDX, 0x0001); /* set/reset enable */ 4063 } 4064} 4065 4066void 4067copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) 4068{ 4069 /* 4070 * FONT KLUDGE: 4071 * This is an interim kludge to display correct font. 4072 * Always use the font page #0 on the video plane 2. 4073 * Somehow we cannot show the font in other font pages on 4074 * some video cards... XXX 4075 */ 4076 font_loading_in_progress = TRUE; 4077 if (operation == LOAD) { 4078 (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256); 4079 if (sc_flags & CHAR_CURSOR) 4080 set_destructive_cursor(scp); 4081 } else if (operation == SAVE) { 4082 (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256); 4083 } 4084 font_loading_in_progress = FALSE; 4085} 4086 4087static void 4088set_destructive_cursor(scr_stat *scp) 4089{ 4090 u_char cursor[32]; 4091 u_char *font_buffer; 4092 int font_size; 4093 int i; 4094 4095 if (!ISFONTAVAIL(get_adapter(scp)->va_flags) 4096 || (scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 4097 return; 4098 4099 if (scp->font_size < 14) { 4100 font_buffer = font_8; 4101 font_size = 8; 4102 } else if (scp->font_size >= 16) { 4103 font_buffer = font_16; 4104 font_size = 16; 4105 } else { 4106 font_buffer = font_14; 4107 font_size = 14; 4108 } 4109 4110 if (scp->status & MOUSE_VISIBLE) { 4111 if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) 4112 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 4113 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1) 4114 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 4115 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2) 4116 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 4117 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3) 4118 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 4119 else 4120 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 4121 cursor, scp->font_size); 4122 } 4123 else 4124 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 4125 cursor, scp->font_size); 4126 for (i=0; i<32; i++) 4127 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 4128 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 4129 cursor[i] |= 0xff; 4130#if 1 4131 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 4132#endif 4133 font_loading_in_progress = TRUE; 4134 (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); 4135 font_loading_in_progress = FALSE; 4136} 4137 4138void 4139sc_move_mouse(scr_stat *scp, int x, int y) 4140{ 4141 scp->mouse_xpos = x; 4142 scp->mouse_ypos = y; 4143 scp->mouse_pos = scp->mouse_oldpos = 4144 scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8; 4145} 4146 4147static void 4148set_mouse_pos(scr_stat *scp) 4149{ 4150 static int last_xpos = -1, last_ypos = -1; 4151 4152 if (scp->mouse_xpos < 0) 4153 scp->mouse_xpos = 0; 4154 if (scp->mouse_ypos < 0) 4155 scp->mouse_ypos = 0; 4156 if (!ISTEXTSC(scp)) { 4157 if (scp->mouse_xpos > scp->xpixel-1) 4158 scp->mouse_xpos = scp->xpixel-1; 4159 if (scp->mouse_ypos > scp->ypixel-1) 4160 scp->mouse_ypos = scp->ypixel-1; 4161 return; 4162 } 4163 if (scp->mouse_xpos > (scp->xsize*8)-1) 4164 scp->mouse_xpos = (scp->xsize*8)-1; 4165 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) 4166 scp->mouse_ypos = (scp->ysize*scp->font_size)-1; 4167 4168 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 4169 scp->status |= MOUSE_MOVED; 4170 4171 scp->mouse_pos = scp->scr_buf + 4172 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 4173 4174 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 4175 mouse_cut(scp); 4176 } 4177} 4178 4179#define isspace(c) (((c) & 0xff) == ' ') 4180 4181static int 4182skip_spc_right(scr_stat *scp, u_short *p) 4183{ 4184 int i; 4185 4186 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4187 if (!isspace(*p)) 4188 break; 4189 ++p; 4190 } 4191 return i; 4192} 4193 4194static int 4195skip_spc_left(scr_stat *scp, u_short *p) 4196{ 4197 int i; 4198 4199 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { 4200 if (!isspace(*p)) 4201 break; 4202 --p; 4203 } 4204 return i; 4205} 4206 4207static void 4208mouse_cut(scr_stat *scp) 4209{ 4210 u_short *end; 4211 u_short *p; 4212 int i = 0; 4213 int j = 0; 4214 4215 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? 4216 scp->mouse_pos + 1 : scp->mouse_pos; 4217 end = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4218 scp->mouse_cut_start : scp->mouse_cut_end; 4219 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4220 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { 4221 cut_buffer[i] = *p & 0xff; 4222 /* remember the position of the last non-space char */ 4223 if (!isspace(cut_buffer[i++])) 4224 j = i; 4225 /* trim trailing blank when crossing lines */ 4226 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 4227 cut_buffer[j++] = '\r'; 4228 i = j; 4229 } 4230 } 4231 cut_buffer[i] = '\0'; 4232 4233 /* scan towards the end of the last line */ 4234 --p; 4235 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4236 if (!isspace(*p)) 4237 break; 4238 ++p; 4239 } 4240 /* if there is nothing but blank chars, trim them, but mark towards eol */ 4241 if (i >= scp->xsize) { 4242 if (scp->mouse_cut_start > scp->mouse_cut_end) 4243 scp->mouse_cut_start = p; 4244 else 4245 scp->mouse_cut_end = p; 4246 cut_buffer[j++] = '\r'; 4247 cut_buffer[j] = '\0'; 4248 } 4249 4250 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 4251 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 4252} 4253 4254static void 4255mouse_cut_start(scr_stat *scp) 4256{ 4257 int i; 4258 4259 if (scp->status & MOUSE_VISIBLE) { 4260 if (scp->mouse_pos == scp->mouse_cut_start && 4261 scp->mouse_cut_start == scp->mouse_cut_end - 1) { 4262 cut_buffer[0] = '\0'; 4263 remove_cutmarking(scp); 4264 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 4265 /* if the pointer is on trailing blank chars, mark towards eol */ 4266 i = skip_spc_left(scp, scp->mouse_pos) + 1; 4267 scp->mouse_cut_start = scp->scr_buf + 4268 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; 4269 scp->mouse_cut_end = scp->scr_buf + 4270 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; 4271 cut_buffer[0] = '\r'; 4272 cut_buffer[1] = '\0'; 4273 scp->status |= MOUSE_CUTTING; 4274 } else { 4275 scp->mouse_cut_start = scp->mouse_pos; 4276 scp->mouse_cut_end = scp->mouse_cut_start + 1; 4277 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 4278 cut_buffer[1] = '\0'; 4279 scp->status |= MOUSE_CUTTING; 4280 } 4281 mark_all(scp); 4282 /* delete all other screens cut markings */ 4283 for (i=0; i<MAXCONS; i++) { 4284 if (console[i] == NULL || console[i] == scp) 4285 continue; 4286 remove_cutmarking(console[i]); 4287 } 4288 } 4289} 4290 4291static void 4292mouse_cut_end(scr_stat *scp) 4293{ 4294 if (scp->status & MOUSE_VISIBLE) { 4295 scp->status &= ~MOUSE_CUTTING; 4296 } 4297} 4298 4299static void 4300mouse_cut_word(scr_stat *scp) 4301{ 4302 u_short *p; 4303 u_short *sol; 4304 u_short *eol; 4305 int i; 4306 4307 /* 4308 * Because we don't have locale information in the kernel, 4309 * we only distinguish space char and non-space chars. Punctuation 4310 * chars, symbols and other regular chars are all treated alike. 4311 */ 4312 if (scp->status & MOUSE_VISIBLE) { 4313 sol = scp->scr_buf 4314 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4315 eol = sol + scp->xsize; 4316 if (isspace(*scp->mouse_pos)) { 4317 for (p = scp->mouse_pos; p >= sol; --p) 4318 if (!isspace(*p)) 4319 break; 4320 scp->mouse_cut_start = ++p; 4321 for (p = scp->mouse_pos; p < eol; ++p) 4322 if (!isspace(*p)) 4323 break; 4324 scp->mouse_cut_end = p; 4325 } else { 4326 for (p = scp->mouse_pos; p >= sol; --p) 4327 if (isspace(*p)) 4328 break; 4329 scp->mouse_cut_start = ++p; 4330 for (p = scp->mouse_pos; p < eol; ++p) 4331 if (isspace(*p)) 4332 break; 4333 scp->mouse_cut_end = p; 4334 } 4335 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4336 cut_buffer[i++] = *p & 0xff; 4337 cut_buffer[i] = '\0'; 4338 scp->status |= MOUSE_CUTTING; 4339 } 4340} 4341 4342static void 4343mouse_cut_line(scr_stat *scp) 4344{ 4345 u_short *p; 4346 int i; 4347 4348 if (scp->status & MOUSE_VISIBLE) { 4349 scp->mouse_cut_start = scp->scr_buf 4350 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4351 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; 4352 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4353 cut_buffer[i++] = *p & 0xff; 4354 cut_buffer[i++] = '\r'; 4355 cut_buffer[i] = '\0'; 4356 scp->status |= MOUSE_CUTTING; 4357 } 4358} 4359 4360static void 4361mouse_cut_extend(scr_stat *scp) 4362{ 4363 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 4364 && (scp->mouse_cut_start != NULL)) { 4365 mouse_cut(scp); 4366 scp->status |= MOUSE_CUTTING; 4367 } 4368} 4369 4370static void 4371mouse_paste(scr_stat *scp) 4372{ 4373 if (scp->status & MOUSE_VISIBLE) { 4374 struct tty *tp; 4375 u_char *ptr = cut_buffer; 4376 4377 tp = VIRTUAL_TTY(get_scr_num()); 4378 while (*ptr) 4379 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 4380 } 4381} 4382 4383static void 4384draw_mouse_image(scr_stat *scp) 4385{ 4386 u_short buffer[32]; 4387 u_short xoffset, yoffset; 4388 u_short *crt_pos = (u_short *)(get_adapter(scp)->va_window) 4389 + (scp->mouse_pos - scp->scr_buf); 4390 u_char *font_buffer; 4391 int font_size; 4392 int i; 4393 4394 if (scp->font_size < 14) { 4395 font_buffer = font_8; 4396 font_size = 8; 4397 } else if (scp->font_size >= 16) { 4398 font_buffer = font_16; 4399 font_size = 16; 4400 } else { 4401 font_buffer = font_14; 4402 font_size = 14; 4403 } 4404 4405 xoffset = scp->mouse_xpos % 8; 4406 yoffset = scp->mouse_ypos % scp->font_size; 4407 4408 /* prepare mousepointer char's bitmaps */ 4409 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 4410 &scp->mouse_cursor[0], font_size); 4411 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 4412 &scp->mouse_cursor[32], font_size); 4413 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 4414 &scp->mouse_cursor[64], font_size); 4415 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 4416 &scp->mouse_cursor[96], font_size); 4417 for (i=0; i<font_size; i++) { 4418 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 4419 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 4420 } 4421 4422 /* now and-or in the mousepointer image */ 4423 for (i=0; i<16; i++) { 4424 buffer[i+yoffset] = 4425 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 4426 | (mouse_or_mask[i] >> xoffset); 4427 } 4428 for (i=0; i<font_size; i++) { 4429 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 4430 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 4431 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 4432 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 4433 } 4434 4435 scp->mouse_oldpos = scp->mouse_pos; 4436 4437#if 1 4438 /* wait for vertical retrace to avoid jitter on some videocards */ 4439 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 4440#endif 4441 font_loading_in_progress = TRUE; 4442 (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, 4443 SC_MOUSE_CHAR, 4); 4444 font_loading_in_progress = FALSE; 4445 4446 *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR; 4447 *(crt_pos+scp->xsize) = 4448 (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2); 4449 if (scp->mouse_xpos < (scp->xsize-1)*8) { 4450 *(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1); 4451 *(crt_pos+scp->xsize + 1) = 4452 (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3); 4453 } 4454 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 4455 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 4456} 4457 4458static void 4459remove_mouse_image(scr_stat *scp) 4460{ 4461 u_short *crt_pos; 4462 4463 if (!ISTEXTSC(scp)) 4464 return; 4465 4466 crt_pos = (u_short *)(get_adapter(scp)->va_window) 4467 + (scp->mouse_oldpos - scp->scr_buf); 4468 *(crt_pos) = *(scp->mouse_oldpos); 4469 *(crt_pos+1) = *(scp->mouse_oldpos+1); 4470 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 4471 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 4472 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 4473 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 4474} 4475 4476static void 4477draw_cutmarking(scr_stat *scp) 4478{ 4479 u_short *crt_pos; 4480 u_short *ptr; 4481 u_short och, nch; 4482 4483 crt_pos = (u_short *)(get_adapter(scp)->va_window); 4484 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 4485 nch = och = *(crt_pos + (ptr - scp->scr_buf)); 4486 /* are we outside the selected area ? */ 4487 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 4488 scp->mouse_cut_end : scp->mouse_cut_start) || 4489 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? 4490 scp->mouse_cut_start : scp->mouse_cut_end)) { 4491 if (ptr != scp->cursor_pos) 4492 nch = (och & 0xff) | (*ptr & 0xff00); 4493 } 4494 else { 4495 /* are we clear of the cursor image ? */ 4496 if (ptr != scp->cursor_pos) 4497 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 4498 else { 4499 if (sc_flags & CHAR_CURSOR) 4500 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 4501 else 4502 if (!(sc_flags & BLINK_CURSOR)) 4503 nch = (och & 0xff) | (*ptr & 0xff00); 4504 } 4505 } 4506 if (nch != och) 4507 *(crt_pos + (ptr - scp->scr_buf)) = nch; 4508 } 4509} 4510 4511static void 4512remove_cutmarking(scr_stat *scp) 4513{ 4514 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 4515 scp->status &= ~MOUSE_CUTTING; 4516 mark_all(scp); 4517} 4518 4519static void 4520do_bell(scr_stat *scp, int pitch, int duration) 4521{ 4522 if (cold || shutdown_in_progress) 4523 return; 4524 4525 if (scp != cur_console && (sc_flags & QUIET_BELL)) 4526 return; 4527 4528 if (sc_flags & VISUAL_BELL) { 4529 if (blink_in_progress) 4530 return; 4531 blink_in_progress = 4; 4532 if (scp != cur_console) 4533 blink_in_progress += 2; 4534 blink_screen(cur_console); 4535 } else { 4536 if (scp != cur_console) 4537 pitch *= 2; 4538 sysbeep(pitch, duration); 4539 } 4540} 4541 4542static void 4543blink_screen(void *arg) 4544{ 4545 scr_stat *scp = arg; 4546 4547 if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { 4548 blink_in_progress = FALSE; 4549 mark_all(scp); 4550 if (delayed_next_scr) 4551 switch_scr(scp, delayed_next_scr - 1); 4552 } 4553 else { 4554 if (blink_in_progress & 1) 4555 fillw(kernel_default.std_color | scr_map[0x20], 4556 (u_short *)(get_adapter(scp)->va_window), 4557 scp->xsize * scp->ysize); 4558 else 4559 fillw(kernel_default.rev_color | scr_map[0x20], 4560 (u_short *)(get_adapter(scp)->va_window), 4561 scp->xsize * scp->ysize); 4562 blink_in_progress--; 4563 timeout(blink_screen, scp, hz / 10); 4564 } 4565} 4566 4567void 4568sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) 4569{ 4570 u_char *font; 4571 u_char volatile *d; 4572 u_char *e; 4573 u_char *f; 4574 int font_size; 4575 int line_length; 4576 int xsize; 4577 u_short bg; 4578 int i, j; 4579 u_char c; 4580 4581 if (ISTEXTSC(scp)) { 4582 generic_bcopy(p + from, (u_short *)(get_adapter(scp)->va_window) + from, 4583 (to - from + 1)*sizeof(u_short)); 4584 } else /* if ISPIXELSC(scp) */ { 4585 if (mark) 4586 mark = 255; 4587 font_size = scp->font_size; 4588 if (font_size < 14) 4589 font = font_8; 4590 else if (font_size >= 16) 4591 font = font_16; 4592 else 4593 font = font_14; 4594 line_length = scp->xpixel/8; 4595 xsize = scp->xsize; 4596 d = (u_char *)(get_adapter(scp)->va_window) 4597 + scp->xoff + scp->yoff*font_size*line_length 4598 + (from%xsize) + font_size*line_length*(from/xsize); 4599 4600 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4601 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4602 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4603 bg = -1; 4604 for (i = from ; i <= to ; i++) { 4605 /* set background color in EGA/VGA latch */ 4606 if (bg != (p[i] & 0xf000)) { 4607 bg = (p[i] & 0xf000); 4608 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4609 outw(GDCIDX, 0xff08); /* bit mask */ 4610 *d = 0; 4611 c = *d; /* set the background color in the latch */ 4612 } 4613 /* foreground color */ 4614 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4615 e = (u_char *)d; 4616 f = &font[(p[i] & 0x00ff)*font_size]; 4617 for (j = 0 ; j < font_size; j++, f++) { 4618 outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */ 4619 *e = 0; 4620 e += line_length; 4621 } 4622 d++; 4623 if ((i % xsize) == xsize - 1) 4624 d += scp->xoff*2 + (font_size - 1)*line_length; 4625 } 4626 outw(GDCIDX, 0x0000); /* set/reset */ 4627 outw(GDCIDX, 0x0001); /* set/reset enable */ 4628 outw(GDCIDX, 0xff08); /* bit mask */ 4629 4630#if 0 /* VGA only */ 4631 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4632 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4633 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4634 outw(GDCIDX, 0xff08); /* bit mask */ 4635 bg = -1; 4636 for (i = from ; i <= to ; i++) { 4637 /* set background color in EGA/VGA latch */ 4638 if (bg != (p[i] & 0xf000)) { 4639 bg = (p[i] & 0xf000); 4640 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4641 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4642 *d = 0; 4643 c = *d; /* set the background color in the latch */ 4644 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4645 } 4646 /* foreground color */ 4647 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4648 e = (u_char *)d; 4649 f = &font[(p[i] & 0x00ff)*font_size]; 4650 for (j = 0 ; j < font_size; j++, f++) { 4651 *e = *f^mark; 4652 e += line_length; 4653 } 4654 d++; 4655 if ((i % xsize) == xsize - 1) 4656 d += scp->xoff*2 + (font_size - 1)*line_length; 4657 } 4658 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4659 outw(GDCIDX, 0x0000); /* set/reset */ 4660 outw(GDCIDX, 0x0001); /* set/reset enable */ 4661#endif /* 0 */ 4662 } 4663} 4664 4665#ifdef SC_SPLASH_SCREEN 4666 4667static void 4668scsplash_init(scr_stat *scp) 4669{ 4670 video_info_t info; 4671 4672 if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) { 4673 default_saver = scsplash_saver; 4674 scrn_blank_time = DEFAULT_BLANKTIME; 4675 run_scrn_saver = TRUE; 4676 if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) { 4677 scsplash_stick(TRUE); 4678 scsplash_saver(TRUE); 4679 } 4680 } 4681} 4682 4683static void 4684scsplash_term(scr_stat *scp) 4685{ 4686 default_saver = none_saver; 4687 scsplash_stick(FALSE); 4688 remove_scrn_saver(scsplash_saver); 4689 scsplash_unload(scp); 4690} 4691 4692static void 4693scsplash_saver(int show) 4694{ 4695 if (show) 4696 scsplash(TRUE); 4697 else if (!sticky_splash) 4698 scsplash(FALSE); 4699} 4700 4701#endif /* SC_SPLASH_SCREEN */ 4702 4703#endif /* NSC */ 4704