syscons.c revision 39742
1333347Speter/*- 2362181Sdim * Copyright (c) 1992-1998 S�ren Schmidt 3333347Speter * All rights reserved. 4333347Speter * 5333347Speter * Redistribution and use in source and binary forms, with or without 6333347Speter * modification, are permitted provided that the following conditions 7333347Speter * are met: 8333347Speter * 1. Redistributions of source code must retain the above copyright 9333347Speter * notice, this list of conditions and the following disclaimer, 10333347Speter * without modification, immediately at the beginning of the file. 11333347Speter * 2. Redistributions in binary form must reproduce the above copyright 12333347Speter * notice, this list of conditions and the following disclaimer in the 13333347Speter * documentation and/or other materials provided with the distribution. 14333347Speter * 3. The name of the author may not be used to endorse or promote products 15333347Speter * derived from this software without specific prior written permission. 16333347Speter * 17333347Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18333347Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19333347Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20333347Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21333347Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22333347Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23333347Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24333347Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25333347Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26333347Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27333347Speter * 28333347Speter * $Id: syscons.c,v 1.281 1998/09/26 03:38:38 yokota Exp $ 29333347Speter */ 30333347Speter 31333347Speter#include "sc.h" 32333347Speter#include "apm.h" 33333347Speter#include "opt_ddb.h" 34333347Speter#include "opt_devfs.h" 35333347Speter#include "opt_vesa.h" 36333347Speter#include "opt_vm86.h" 37333347Speter#include "opt_syscons.h" 38333347Speter 39333347Speter#if NSC > 0 40333347Speter#include <sys/param.h> 41333347Speter#include <sys/systm.h> 42333347Speter#include <sys/reboot.h> 43333347Speter#include <sys/conf.h> 44333347Speter#include <sys/proc.h> 45333347Speter#include <sys/signalvar.h> 46333347Speter#include <sys/tty.h> 47333347Speter#include <sys/kernel.h> 48333347Speter#include <sys/malloc.h> 49333347Speter#ifdef DEVFS 50333347Speter#include <sys/devfsext.h> 51333347Speter#endif 52333347Speter 53333347Speter#include <machine/bootinfo.h> 54333347Speter#include <machine/clock.h> 55333347Speter#include <machine/cons.h> 56333347Speter#include <machine/console.h> 57333347Speter#include <machine/mouse.h> 58333347Speter#include <machine/md_var.h> 59333347Speter#include <machine/psl.h> 60333347Speter#include <machine/frame.h> 61333347Speter#include <machine/pc/display.h> 62333347Speter#include <machine/pc/vesa.h> 63333347Speter#include <machine/apm_bios.h> 64333347Speter#include <machine/random.h> 65333347Speter 66333347Speter#include <vm/vm.h> 67333347Speter#include <vm/vm_param.h> 68333347Speter#include <vm/pmap.h> 69333347Speter 70333347Speter#include <i386/isa/isa.h> 71333347Speter#include <i386/isa/isa_device.h> 72333347Speter#include <i386/isa/timerreg.h> 73333347Speter#include <i386/isa/kbdtables.h> 74333347Speter#include <i386/isa/kbdio.h> 75333347Speter#include <i386/isa/videoio.h> 76333347Speter#include <i386/isa/syscons.h> 77333347Speter 78333347Speter#if !defined(MAXCONS) 79333347Speter#define MAXCONS 16 80333347Speter#endif 81333347Speter 82333347Speter#if !defined(SC_MAX_HISTORY_SIZE) 83333347Speter#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS) 84333347Speter#endif 85333347Speter 86333347Speter#if !defined(SC_HISTORY_SIZE) 87333347Speter#define SC_HISTORY_SIZE (ROW * 4) 88333347Speter#endif 89333347Speter 90333347Speter#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE 91333347Speter#undef SC_MAX_HISTORY_SIZE 92333347Speter#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS) 93333347Speter#endif 94333347Speter 95333347Speter#if !defined(SC_MOUSE_CHAR) 96333347Speter#define SC_MOUSE_CHAR (0xd0) 97333347Speter#endif 98333347Speter 99333347Speter#define COLD 0 100333347Speter#define WARM 1 101333347Speter 102333347Speter#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ 103333347Speter#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ 104333347Speter 105333347Speter/* for backward compatibility */ 106333347Speter#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 107333347Speter 108333347Spetertypedef struct old_mouse_data { 109333347Speter int x; 110333347Speter int y; 111333347Speter int buttons; 112333347Speter} old_mouse_data_t; 113333347Speter 114333347Spetertypedef struct old_mouse_info { 115333347Speter int operation; 116333347Speter union { 117333347Speter struct old_mouse_data data; 118333347Speter struct mouse_mode mode; 119333347Speter } u; 120333347Speter} old_mouse_info_t; 121333347Speter 122333347Speter/* XXX use sc_bcopy where video memory is concerned */ 123333347Speterextern void generic_bcopy(const void *, void *, size_t); 124333347Speterextern void generic_bzero(void *, size_t); 125333347Speter 126333347Speterstatic default_attr user_default = { 127333347Speter (FG_LIGHTGREY | BG_BLACK) << 8, 128333347Speter (FG_BLACK | BG_LIGHTGREY) << 8 129333347Speter}; 130333347Speter 131333347Speterstatic default_attr kernel_default = { 132333347Speter (FG_WHITE | BG_BLACK) << 8, 133333347Speter (FG_BLACK | BG_LIGHTGREY) << 8 134333347Speter}; 135333347Speter 136333347Speterstatic scr_stat main_console; 137333347Speterstatic scr_stat *console[MAXCONS]; 138333347Speter#ifdef DEVFS 139333347Speterstatic void *sc_devfs_token[MAXCONS]; 140333347Speterstatic void *sc_mouse_devfs_token; 141333347Speterstatic void *sc_console_devfs_token; 142333347Speter#endif 143333347Speter scr_stat *cur_console; 144333347Speterstatic scr_stat *new_scp, *old_scp; 145333347Speterstatic term_stat kernel_console; 146333347Speterstatic default_attr *current_default; 147333347Speter int sc_flags; 148333347Speterstatic int sc_port = IO_KBD; 149333347Speterstatic KBDC sc_kbdc = NULL; 150333347Speterstatic char init_done = COLD; 151333347Speterstatic u_short sc_buffer[ROW*COL]; 152333347Speterstatic char shutdown_in_progress = FALSE; 153333347Speterstatic char font_loading_in_progress = FALSE; 154333347Speterstatic char switch_in_progress = FALSE; 155333347Speterstatic char write_in_progress = FALSE; 156333347Speterstatic char blink_in_progress = FALSE; 157333347Speterstatic int blinkrate = 0; 158333347Speter u_int crtc_addr = MONO_BASE; 159333347Speter char crtc_type = KD_MONO; 160333347Speterstatic char crtc_vga = FALSE; 161333347Speterstatic int adp_flags; 162333347Speterstatic u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 163333347Speterstatic u_char accents = 0; 164333347Speterstatic u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 165333347Speterstatic const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 166333347Speterstatic int delayed_next_scr = FALSE; 167333347Speterstatic long scrn_blank_time = 0; /* screen saver timeout value */ 168333347Speter int scrn_blanked = 0; /* screen saver active flag */ 169333347Speterstatic long scrn_time_stamp; 170333347Speterstatic int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */ 171333347Speterstatic int run_scrn_saver = FALSE; /* should run the saver? */ 172333347Speterstatic int scrn_idle = FALSE; /* about to run the saver */ 173333347Speter u_char scr_map[256]; 174333347Speter u_char scr_rmap[256]; 175333347Speterstatic int initial_video_mode; /* initial video mode # */ 176333347Speterstatic int bios_video_mode; /* video mode # set by BIOS */ 177333347Speter int fonts_loaded = 0 178333347Speter#ifdef STD8X16FONT 179333347Speter | FONT_16 180333347Speter#endif 181333347Speter ; 182333347Speter 183333347Speter u_char font_8[256*8]; 184333347Speter u_char font_14[256*14]; 185333347Speter#ifdef STD8X16FONT 186333347Speterextern 187333347Speter#endif 188333347Speter u_char font_16[256*16]; 189333347Speter u_char palette[256*3]; 190333347Speterstatic u_char *cut_buffer; 191333347Speterstatic int cut_buffer_size; 192333347Speterstatic int mouse_level; /* sysmouse protocol level */ 193333347Speterstatic mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; 194333347Speterstatic u_short mouse_and_mask[16] = { 195333347Speter 0xc000, 0xe000, 0xf000, 0xf800, 196333347Speter 0xfc00, 0xfe00, 0xff00, 0xff80, 197333347Speter 0xfe00, 0x1e00, 0x1f00, 0x0f00, 198333347Speter 0x0f00, 0x0000, 0x0000, 0x0000 199333347Speter }; 200333347Speterstatic u_short mouse_or_mask[16] = { 201333347Speter 0x0000, 0x4000, 0x6000, 0x7000, 202333347Speter 0x7800, 0x7c00, 0x7e00, 0x6800, 203333347Speter 0x0c00, 0x0c00, 0x0600, 0x0600, 204333347Speter 0x0000, 0x0000, 0x0000, 0x0000 205333347Speter }; 206333347Speter 207333347Speter int sc_history_size = SC_HISTORY_SIZE; 208333347Speterstatic int extra_history_size = 209333347Speter SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; 210333347Speter 211333347Speterstatic void none_saver(int blank) { } 212333347Speterstatic void (*current_saver)(int blank) = none_saver; 213333347Speterstatic void (*default_saver)(int blank) = none_saver; 214333347Speter d_ioctl_t *sc_user_ioctl; 215333347Speter 216333347Speterstatic int sticky_splash = FALSE; 217333347Speter 218333347Speter/* OS specific stuff */ 219333347Speter#ifdef not_yet_done 220333347Speter#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 221333347Speterstruct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 222333347Speterstruct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) 223333347Speterstruct tty *sccons[MAXCONS+2]; 224333347Speter#else 225333347Speter#define VIRTUAL_TTY(x) &sccons[x] 226333347Speter#define CONSOLE_TTY &sccons[MAXCONS] 227333347Speter#define MOUSE_TTY &sccons[MAXCONS+1] 228333347Speterstatic struct tty sccons[MAXCONS+2]; 229333347Speter#endif 230333347Speter#define SC_MOUSE 128 231333347Speter#define SC_CONSOLE 255 232333347Speteru_short *Crtat; 233333347Speterstatic const int nsccons = MAXCONS+2; 234333347Speter 235333347Speter#define WRAPHIST(scp, pointer, offset)\ 236333347Speter ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ 237333347Speter + (offset)) % (scp)->history_size)) 238333347Speter#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 239333347Speter 240333347Speter/* prototypes */ 241333347Speterstatic int scattach(struct isa_device *dev); 242333347Speterstatic int scparam(struct tty *tp, struct termios *t); 243333347Speterstatic int scprobe(struct isa_device *dev); 244333347Speterstatic int scvidprobe(int unit, int flags); 245333347Speterstatic int sckbdprobe(int unit, int flags); 246333347Speterstatic void scstart(struct tty *tp); 247333347Speterstatic void scmousestart(struct tty *tp); 248333347Speterstatic void scinit(void); 249333347Speterstatic void scshutdown(int howto, void *arg); 250333347Speterstatic u_int scgetc(u_int flags); 251333347Speter#define SCGETC_CN 1 252333347Speter#define SCGETC_NONBLOCK 2 253333347Speterstatic void sccnupdate(scr_stat *scp); 254333347Speterstatic scr_stat *alloc_scp(void); 255333347Speterstatic void init_scp(scr_stat *scp); 256333347Speterstatic void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); 257333347Speterstatic int get_scr_num(void); 258333347Speterstatic timeout_t scrn_timer; 259333347Speterstatic void scrn_update(scr_stat *scp, int show_cursor); 260333347Speterstatic void scrn_saver(void (*saver)(int), int blank); 261333347Speterstatic void stop_scrn_saver(void (*saver)(int)); 262333347Speterstatic int wait_scrn_saver_stop(void); 263333347Speterstatic int switch_scr(scr_stat *scp, u_int next_scr); 264333347Speterstatic void exchange_scr(void); 265333347Speterstatic void scan_esc(scr_stat *scp, u_char c); 266333347Speterstatic void ansi_put(scr_stat *scp, u_char *buf, int len); 267333347Speterstatic void draw_cursor_image(scr_stat *scp); 268333347Speterstatic void remove_cursor_image(scr_stat *scp); 269333347Speterstatic void move_crsr(scr_stat *scp, int x, int y); 270333347Speterstatic u_char *get_fstr(u_int c, u_int *len); 271333347Speterstatic void history_to_screen(scr_stat *scp); 272333347Speterstatic int history_up_line(scr_stat *scp); 273333347Speterstatic int history_down_line(scr_stat *scp); 274333347Speterstatic int mask2attr(struct term_stat *term); 275333347Speterstatic void set_keyboard(int command, int data); 276333347Speterstatic void update_leds(int which); 277333347Speterstatic void set_mouse_pos(scr_stat *scp); 278333347Speterstatic int skip_spc_right(scr_stat *scp, u_short *p); 279333347Speterstatic int skip_spc_left(scr_stat *scp, u_short *p); 280333347Speterstatic void mouse_cut(scr_stat *scp); 281333347Speterstatic void mouse_cut_start(scr_stat *scp); 282333347Speterstatic void mouse_cut_end(scr_stat *scp); 283333347Speterstatic void mouse_cut_word(scr_stat *scp); 284333347Speterstatic void mouse_cut_line(scr_stat *scp); 285333347Speterstatic void mouse_cut_extend(scr_stat *scp); 286333347Speterstatic void mouse_paste(scr_stat *scp); 287333347Speterstatic void draw_mouse_image(scr_stat *scp); 288333347Speterstatic void remove_mouse_image(scr_stat *scp); 289333347Speterstatic void draw_cutmarking(scr_stat *scp); 290333347Speterstatic void remove_cutmarking(scr_stat *scp); 291333347Speterstatic void do_bell(scr_stat *scp, int pitch, int duration); 292333347Speterstatic timeout_t blink_screen; 293333347Speter#ifdef SC_SPLASH_SCREEN 294333347Speterstatic void scsplash_init(scr_stat *scp); 295333347Speterstatic void scsplash_term(scr_stat *scp); 296333347Speterstatic void scsplash_saver(int show); 297333347Speter#define scsplash_stick(stick) (sticky_splash = (stick)) 298333347Speter#else 299333347Speter#define scsplash_stick(stick) 300333347Speter#endif 301333347Speter 302333347Speterstruct isa_driver scdriver = { 303333347Speter scprobe, scattach, "sc", 1 304333347Speter}; 305333347Speter 306333347Speterstatic d_open_t scopen; 307333347Speterstatic d_close_t scclose; 308333347Speterstatic d_read_t scread; 309333347Speterstatic d_write_t scwrite; 310333347Speterstatic d_ioctl_t scioctl; 311333347Speterstatic d_mmap_t scmmap; 312333347Speter 313333347Speter#define CDEV_MAJOR 12 314333347Speterstatic struct cdevsw sc_cdevsw = { 315333347Speter scopen, scclose, scread, scwrite, 316333347Speter scioctl, nullstop, noreset, scdevtotty, 317333347Speter ttpoll, scmmap, nostrategy, "sc", 318333347Speter NULL, -1, nodump, nopsize, 319333347Speter D_TTY, 320333347Speter}; 321333347Speter 322333347Speterstatic void 323333347Speterdraw_cursor_image(scr_stat *scp) 324333347Speter{ 325333347Speter u_short cursor_image; 326333347Speter u_short *ptr; 327333347Speter u_short prev_image; 328333347Speter 329333347Speter if (ISPIXELSC(scp)) { 330333347Speter sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 331333347Speter scp->cursor_pos - scp->scr_buf, 1); 332333347Speter return; 333333347Speter } 334333347Speter 335333347Speter ptr = (u_short *)(get_adapter(scp)->va_window) 336333347Speter + (scp->cursor_pos - scp->scr_buf); 337333347Speter 338333347Speter /* do we have a destructive cursor ? */ 339333347Speter if (sc_flags & CHAR_CURSOR) { 340333347Speter prev_image = scp->cursor_saveunder; 341333347Speter cursor_image = *ptr & 0x00ff; 342333347Speter if (cursor_image == DEAD_CHAR) 343333347Speter cursor_image = prev_image & 0x00ff; 344333347Speter cursor_image |= *(scp->cursor_pos) & 0xff00; 345333347Speter scp->cursor_saveunder = cursor_image; 346333347Speter /* update the cursor bitmap if the char under the cursor has changed */ 347333347Speter if (prev_image != cursor_image) 348333347Speter set_destructive_cursor(scp); 349333347Speter /* modify cursor_image */ 350333347Speter if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 351333347Speter /* 352333347Speter * When the mouse pointer is at the same position as the cursor, 353333347Speter * the cursor bitmap needs to be updated even if the char under 354333347Speter * the cursor hasn't changed, because the mouse pionter may 355333347Speter * have moved by a few dots within the cursor cel. 356333347Speter */ 357333347Speter if ((prev_image == cursor_image) 358333347Speter && (cursor_image != *(scp->cursor_pos))) 359333347Speter set_destructive_cursor(scp); 360333347Speter cursor_image &= 0xff00; 361333347Speter cursor_image |= DEAD_CHAR; 362333347Speter } 363333347Speter } else { 364333347Speter cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; 365333347Speter scp->cursor_saveunder = cursor_image; 366333347Speter if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 367333347Speter if ((cursor_image & 0x7000) == 0x7000) { 368333347Speter cursor_image &= 0x8fff; 369333347Speter if(!(cursor_image & 0x0700)) 370333347Speter cursor_image |= 0x0700; 371333347Speter } else { 372333347Speter cursor_image |= 0x7000; 373333347Speter if ((cursor_image & 0x0700) == 0x0700) 374333347Speter cursor_image &= 0xf0ff; 375333347Speter } 376333347Speter } 377333347Speter } 378333347Speter *ptr = cursor_image; 379333347Speter} 380333347Speter 381333347Speterstatic void 382333347Speterremove_cursor_image(scr_stat *scp) 383333347Speter{ 384333347Speter if (ISPIXELSC(scp)) 385333347Speter sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 386333347Speter scp->cursor_oldpos - scp->scr_buf, 0); 387333347Speter else 388333347Speter *((u_short *)(get_adapter(scp)->va_window) 389333347Speter + (scp->cursor_oldpos - scp->scr_buf)) 390333347Speter = scp->cursor_saveunder; 391333347Speter} 392333347Speter 393333347Speterstatic void 394333347Spetermove_crsr(scr_stat *scp, int x, int y) 395333347Speter{ 396333347Speter if (x < 0) 397333347Speter x = 0; 398333347Speter if (y < 0) 399333347Speter y = 0; 400333347Speter if (x >= scp->xsize) 401333347Speter x = scp->xsize-1; 402333347Speter if (y >= scp->ysize) 403333347Speter y = scp->ysize-1; 404333347Speter scp->xpos = x; 405333347Speter scp->ypos = y; 406333347Speter scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 407333347Speter} 408333347Speter 409333347Speterstatic int 410333347Speterscprobe(struct isa_device *dev) 411333347Speter{ 412333347Speter if (!scvidprobe(dev->id_unit, dev->id_flags)) { 413333347Speter if (bootverbose) 414333347Speter printf("sc%d: no video adapter is found.\n", dev->id_unit); 415333347Speter return (0); 416333347Speter } 417333347Speter 418333347Speter#if defined(VESA) && defined(VM86) 419333347Speter if (vesa_load()) 420333347Speter return FALSE; 421333347Speter#endif 422333347Speter 423333347Speter (*biosvidsw.diag)(bootverbose); 424333347Speter 425333347Speter sc_port = dev->id_iobase; 426333347Speter if (sckbdprobe(dev->id_unit, dev->id_flags)) 427333347Speter return (IO_KBDSIZE); 428333347Speter else 429333347Speter return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); 430333347Speter} 431333347Speter 432333347Speter/* probe video adapters, return TRUE if found */ 433333347Speterstatic int 434333347Speterscvidprobe(int unit, int flags) 435333347Speter{ 436333347Speter video_adapter_t *adp; 437333347Speter 438333347Speter /* do this test only once */ 439333347Speter if (init_done != COLD) 440333347Speter return (crtc_type != -1); 441333347Speter 442333347Speter if ((*biosvidsw.init)() <= 0) 443333347Speter return FALSE; 444333347Speter if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL) 445333347Speter return FALSE; 446333347Speter 447333347Speter crtc_type = adp->va_type; 448333347Speter crtc_vga = (crtc_type == KD_VGA); 449333347Speter crtc_addr = adp->va_crtc_addr; 450333347Speter Crtat = (u_short *)adp->va_window; 451333347Speter adp_flags = adp->va_flags; 452333347Speter initial_video_mode = adp->va_initial_mode; 453333347Speter bios_video_mode = adp->va_initial_bios_mode; 454333347Speter 455333347Speter return TRUE; 456333347Speter} 457333347Speter 458333347Speter/* probe the keyboard, return TRUE if found */ 459333347Speterstatic int 460333347Spetersckbdprobe(int unit, int flags) 461333347Speter{ 462333347Speter int codeset; 463333347Speter int c = -1; 464333347Speter int m; 465333347Speter int res, id; 466333347Speter 467333347Speter sc_kbdc = kbdc_open(sc_port); 468333347Speter 469333347Speter if (!kbdc_lock(sc_kbdc, TRUE)) { 470333347Speter /* driver error? */ 471333347Speter printf("sc%d: unable to lock the controller.\n", unit); 472333347Speter return ((flags & DETECT_KBD) ? FALSE : TRUE); 473333347Speter } 474333347Speter 475333347Speter /* flush any noise in the buffer */ 476333347Speter empty_both_buffers(sc_kbdc, 10); 477333347Speter 478333347Speter /* save the current keyboard controller command byte */ 479333347Speter m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; 480333347Speter c = get_controller_command_byte(sc_kbdc); 481333347Speter if (c == -1) { 482333347Speter /* CONTROLLER ERROR */ 483333347Speter printf("sc%d: unable to get the current command byte value.\n", unit); 484333347Speter goto fail; 485333347Speter } 486333347Speter if (bootverbose) 487333347Speter printf("sc%d: the current keyboard controller command byte %04x\n", 488333347Speter unit, c); 489333347Speter#if 0 490333347Speter /* override the keyboard lock switch */ 491333347Speter c |= KBD_OVERRIDE_KBD_LOCK; 492333347Speter#endif 493333347Speter 494333347Speter /* 495333347Speter * The keyboard may have been screwed up by the boot block. 496333347Speter * We may just be able to recover from error by testing the controller 497333347Speter * and the keyboard port. The controller command byte needs to be saved 498333347Speter * before this recovery operation, as some controllers seem to set 499333347Speter * the command byte to particular values. 500333347Speter */ 501333347Speter test_controller(sc_kbdc); 502333347Speter test_kbd_port(sc_kbdc); 503333347Speter 504333347Speter /* enable the keyboard port, but disable the keyboard intr. */ 505333347Speter if (!set_controller_command_byte(sc_kbdc, 506333347Speter KBD_KBD_CONTROL_BITS, 507333347Speter KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { 508333347Speter /* CONTROLLER ERROR 509333347Speter * there is very little we can do... 510333347Speter */ 511333347Speter printf("sc%d: unable to set the command byte.\n", unit); 512333347Speter goto fail; 513333347Speter } 514333347Speter 515333347Speter /* 516333347Speter * Check if we have an XT keyboard before we attempt to reset it. 517333347Speter * The procedure assumes that the keyboard and the controller have 518333347Speter * been set up properly by BIOS and have not been messed up 519333347Speter * during the boot process. 520333347Speter */ 521333347Speter codeset = -1; 522333347Speter if (flags & XT_KEYBD) 523333347Speter /* the user says there is a XT keyboard */ 524333347Speter codeset = 1; 525333347Speter#ifdef DETECT_XT_KEYBOARD 526333347Speter else if ((c & KBD_TRANSLATION) == 0) { 527333347Speter /* SET_SCANCODE_SET is not always supported; ignore error */ 528333347Speter if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) 529333347Speter == KBD_ACK) 530333347Speter codeset = read_kbd_data(sc_kbdc); 531333347Speter } 532333347Speter if (bootverbose) 533333347Speter printf("sc%d: keyboard scancode set %d\n", unit, codeset); 534333347Speter#endif /* DETECT_XT_KEYBOARD */ 535333347Speter 536333347Speter if (flags & KBD_NORESET) { 537333347Speter write_kbd_command(sc_kbdc, KBDC_ECHO); 538333347Speter if (read_kbd_data(sc_kbdc) != KBD_ECHO) { 539333347Speter empty_both_buffers(sc_kbdc, 10); 540333347Speter test_controller(sc_kbdc); 541333347Speter test_kbd_port(sc_kbdc); 542333347Speter if (bootverbose) 543333347Speter printf("sc%d: failed to get response from the keyboard.\n", 544333347Speter unit); 545333347Speter goto fail; 546333347Speter } 547333347Speter } else { 548333347Speter /* reset keyboard hardware */ 549333347Speter if (!reset_kbd(sc_kbdc)) { 550333347Speter /* KEYBOARD ERROR 551333347Speter * Keyboard reset may fail either because the keyboard doen't 552333347Speter * exist, or because the keyboard doesn't pass the self-test, 553333347Speter * or the keyboard controller on the motherboard and the keyboard 554333347Speter * somehow fail to shake hands. It is just possible, particularly 555333347Speter * in the last case, that the keyoard controller may be left 556333347Speter * in a hung state. test_controller() and test_kbd_port() appear 557333347Speter * to bring the keyboard controller back (I don't know why and 558333347Speter * how, though.) 559333347Speter */ 560333347Speter empty_both_buffers(sc_kbdc, 10); 561333347Speter test_controller(sc_kbdc); 562333347Speter test_kbd_port(sc_kbdc); 563333347Speter /* We could disable the keyboard port and interrupt... but, 564333347Speter * the keyboard may still exist (see above). 565333347Speter */ 566333347Speter if (bootverbose) 567333347Speter printf("sc%d: failed to reset the keyboard.\n", unit); 568333347Speter goto fail; 569333347Speter } 570333347Speter } 571333347Speter 572333347Speter /* 573333347Speter * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards 574333347Speter * such as those on the IBM ThinkPad laptop computers can be used 575333347Speter * with the standard console driver. 576333347Speter */ 577333347Speter if (codeset == 1) { 578333347Speter if (send_kbd_command_and_data( 579333347Speter sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 580333347Speter /* XT kbd doesn't need scan code translation */ 581333347Speter c &= ~KBD_TRANSLATION; 582333347Speter } else { 583333347Speter /* KEYBOARD ERROR 584333347Speter * The XT kbd isn't usable unless the proper scan code set 585333347Speter * is selected. 586333347Speter */ 587333347Speter printf("sc%d: unable to set the XT keyboard mode.\n", unit); 588333347Speter goto fail; 589333347Speter } 590333347Speter } 591333347Speter /* enable the keyboard port and intr. */ 592333347Speter if (!set_controller_command_byte(sc_kbdc, 593333347Speter KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 594333347Speter (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 595333347Speter | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 596333347Speter /* CONTROLLER ERROR 597333347Speter * This is serious; we are left with the disabled keyboard intr. 598333347Speter */ 599333347Speter printf("sc%d: unable to enable the keyboard port and intr.\n", unit); 600333347Speter goto fail; 601333347Speter } 602333347Speter 603333347Speter /* Get the ID of the keyboard, if any */ 604333347Speter empty_kbd_buffer(sc_kbdc, 5); 605333347Speter res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID); 606333347Speter if (res == KBD_ACK) { 607333347Speter /* 10ms delay */ 608333347Speter DELAY(10000); 609333347Speter id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc); 610333347Speter if (bootverbose) 611333347Speter printf("sc%d: keyboard device ID: %04x\n", unit, id); 612333347Speter } 613333347Speter 614333347Speter kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), 615333347Speter kbdc_lock(sc_kbdc, FALSE); 616333347Speter return TRUE; 617333347Speter 618333347Speterfail: 619333347Speter if (c != -1) 620333347Speter /* try to restore the command byte as before, if possible */ 621333347Speter set_controller_command_byte(sc_kbdc, 0xff, c); 622333347Speter kbdc_set_device_mask(sc_kbdc, 623333347Speter (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); 624333347Speter kbdc_lock(sc_kbdc, FALSE); 625333347Speter return FALSE; 626333347Speter} 627333347Speter 628333347Speter#if NAPM > 0 629333347Speterstatic int 630333347Speterscresume(void *dummy) 631333347Speter{ 632333347Speter shfts = ctls = alts = agrs = metas = accents = 0; 633333347Speter return 0; 634333347Speter} 635333347Speter#endif 636333347Speter 637333347Speterstatic int 638333347Speterscattach(struct isa_device *dev) 639333347Speter{ 640333347Speter scr_stat *scp; 641333347Speter video_info_t info; 642333347Speter dev_t cdev = makedev(CDEV_MAJOR, 0); 643333347Speter#ifdef DEVFS 644333347Speter int vc; 645333347Speter#endif 646333347Speter 647333347Speter scinit(); 648333347Speter sc_flags = dev->id_flags; 649333347Speter if (!ISFONTAVAIL(adp_flags)) 650333347Speter sc_flags &= ~CHAR_CURSOR; 651333347Speter 652333347Speter scp = console[0]; 653333347Speter 654333347Speter /* copy temporary buffer to final buffer */ 655333347Speter scp->scr_buf = NULL; 656333347Speter sc_alloc_scr_buffer(scp, FALSE, FALSE); 657333347Speter bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short)); 658333347Speter 659333347Speter /* cut buffer is available only when the mouse pointer is used */ 660333347Speter if (ISMOUSEAVAIL(adp_flags)) 661333347Speter sc_alloc_cut_buffer(scp, FALSE); 662333347Speter 663333347Speter /* initialize history buffer & pointers */ 664333347Speter sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); 665333347Speter 666333347Speter#if defined(VESA) && defined(VM86) 667333347Speter if ((sc_flags & VESA800X600) 668333347Speter && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { 669333347Speter#ifdef SC_SPLASH_SCREEN 670333347Speter scsplash_term(scp); 671333347Speter#endif 672333347Speter sc_set_graphics_mode(scp, NULL, M_VESA_800x600); 673333347Speter sc_set_pixel_mode(scp, NULL, COL, ROW, 16); 674333347Speter initial_video_mode = M_VESA_800x600; 675333347Speter#ifdef SC_SPLASH_SCREEN 676333347Speter scsplash_init(scp); 677333347Speter#endif 678333347Speter } 679333347Speter#endif /* VESA && VM86 */ 680333347Speter 681333347Speter /* initialize cursor stuff */ 682333347Speter if (!ISGRAPHSC(scp)) 683333347Speter draw_cursor_image(scp); 684333347Speter 685333347Speter /* get screen update going */ 686333347Speter scrn_timer((void *)TRUE); 687333347Speter 688333347Speter update_leds(scp->status); 689333347Speter 690333347Speter printf("sc%d: ", dev->id_unit); 691333347Speter switch(crtc_type) { 692333347Speter case KD_VGA: 693333347Speter printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); 694333347Speter break; 695333347Speter case KD_EGA: 696333347Speter printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); 697333347Speter break; 698333347Speter case KD_CGA: 699333347Speter printf("CGA"); 700333347Speter break; 701333347Speter case KD_MONO: 702333347Speter case KD_HERCULES: 703333347Speter default: 704333347Speter printf("MDA/Hercules"); 705333347Speter break; 706333347Speter } 707333347Speter printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, sc_flags); 708333347Speter 709333347Speter#if NAPM > 0 710333347Speter scp->r_hook.ah_fun = scresume; 711333347Speter scp->r_hook.ah_arg = NULL; 712333347Speter scp->r_hook.ah_name = "system keyboard"; 713333347Speter scp->r_hook.ah_order = APM_MID_ORDER; 714333347Speter apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 715333347Speter#endif 716333347Speter 717333347Speter at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC); 718333347Speter 719333347Speter cdevsw_add(&cdev, &sc_cdevsw, NULL); 720333347Speter 721333347Speter#ifdef DEVFS 722333347Speter for (vc = 0; vc < MAXCONS; vc++) 723333347Speter sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR, 724333347Speter UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc); 725333347Speter sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR, 726333347Speter UID_ROOT, GID_WHEEL, 0600, "sysmouse"); 727333347Speter sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR, 728333347Speter UID_ROOT, GID_WHEEL, 0600, "consolectl"); 729333347Speter#endif 730333347Speter return 0; 731333347Speter} 732333347Speter 733333347Speterstruct tty 734333347Speter*scdevtotty(dev_t dev) 735333347Speter{ 736333347Speter int unit = minor(dev); 737333347Speter 738333347Speter if (init_done == COLD) 739333347Speter return(NULL); 740333347Speter if (unit == SC_CONSOLE) 741333347Speter return CONSOLE_TTY; 742333347Speter if (unit == SC_MOUSE) 743333347Speter return MOUSE_TTY; 744333347Speter if (unit >= MAXCONS || unit < 0) 745333347Speter return(NULL); 746333347Speter return VIRTUAL_TTY(unit); 747333347Speter} 748333347Speter 749333347Speterint 750333347Speterscopen(dev_t dev, int flag, int mode, struct proc *p) 751333347Speter{ 752333347Speter struct tty *tp = scdevtotty(dev); 753333347Speter 754333347Speter if (!tp) 755333347Speter return(ENXIO); 756333347Speter 757333347Speter tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; 758333347Speter tp->t_param = scparam; 759333347Speter tp->t_dev = dev; 760333347Speter if (!(tp->t_state & TS_ISOPEN)) { 761333347Speter ttychars(tp); 762333347Speter /* Use the current setting of the <-- key as default VERASE. */ 763333347Speter /* If the Delete key is preferable, an stty is necessary */ 764333347Speter tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; 765333347Speter tp->t_iflag = TTYDEF_IFLAG; 766333347Speter tp->t_oflag = TTYDEF_OFLAG; 767333347Speter tp->t_cflag = TTYDEF_CFLAG; 768333347Speter tp->t_lflag = TTYDEF_LFLAG; 769333347Speter tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 770333347Speter scparam(tp, &tp->t_termios); 771333347Speter (*linesw[tp->t_line].l_modem)(tp, 1); 772333347Speter if (minor(dev) == SC_MOUSE) 773333347Speter mouse_level = 0; /* XXX */ 774333347Speter } 775333347Speter else 776333347Speter if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 777333347Speter return(EBUSY); 778333347Speter if (minor(dev) < MAXCONS && !console[minor(dev)]) { 779333347Speter console[minor(dev)] = alloc_scp(); 780333347Speter if (ISGRAPHSC(console[minor(dev)])) 781333347Speter sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16); 782333347Speter } 783333347Speter if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 784333347Speter tp->t_winsize.ws_col = console[minor(dev)]->xsize; 785333347Speter tp->t_winsize.ws_row = console[minor(dev)]->ysize; 786333347Speter } 787333347Speter return ((*linesw[tp->t_line].l_open)(dev, tp)); 788333347Speter} 789333347Speter 790333347Speterint 791333347Speterscclose(dev_t dev, int flag, int mode, struct proc *p) 792333347Speter{ 793333347Speter struct tty *tp = scdevtotty(dev); 794333347Speter struct scr_stat *scp; 795333347Speter 796333347Speter if (!tp) 797333347Speter return(ENXIO); 798333347Speter if (minor(dev) < MAXCONS) { 799333347Speter scp = sc_get_scr_stat(tp->t_dev); 800333347Speter if (scp->status & SWITCH_WAIT_ACQ) 801333347Speter wakeup((caddr_t)&scp->smode); 802333347Speter#if not_yet_done 803333347Speter if (scp == &main_console) { 804333347Speter scp->pid = 0; 805333347Speter scp->proc = NULL; 806333347Speter scp->smode.mode = VT_AUTO; 807333347Speter } 808333347Speter else { 809333347Speter free(scp->scr_buf, M_DEVBUF); 810333347Speter if (scp->history != NULL) { 811333347Speter free(scp->history, M_DEVBUF); 812333347Speter if (scp->history_size / scp->xsize 813333347Speter > imax(sc_history_size, scp->ysize)) 814333347Speter extra_history_size += scp->history_size / scp->xsize 815333347Speter - imax(sc_history_size, scp->ysize); 816333347Speter } 817333347Speter free(scp, M_DEVBUF); 818333347Speter console[minor(dev)] = NULL; 819333347Speter } 820333347Speter#else 821333347Speter scp->pid = 0; 822333347Speter scp->proc = NULL; 823333347Speter scp->smode.mode = VT_AUTO; 824333347Speter#endif 825333347Speter } 826333347Speter spltty(); 827333347Speter (*linesw[tp->t_line].l_close)(tp, flag); 828333347Speter ttyclose(tp); 829333347Speter spl0(); 830333347Speter return(0); 831333347Speter} 832333347Speter 833333347Speterint 834333347Speterscread(dev_t dev, struct uio *uio, int flag) 835333347Speter{ 836333347Speter struct tty *tp = scdevtotty(dev); 837333347Speter 838333347Speter if (!tp) 839333347Speter return(ENXIO); 840333347Speter return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 841333347Speter} 842333347Speter 843333347Speterint 844333347Speterscwrite(dev_t dev, struct uio *uio, int flag) 845333347Speter{ 846333347Speter struct tty *tp = scdevtotty(dev); 847333347Speter 848333347Speter if (!tp) 849333347Speter return(ENXIO); 850333347Speter return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 851333347Speter} 852333347Speter 853333347Spetervoid 854333347Speterscintr(int unit) 855333347Speter{ 856333347Speter static struct tty *cur_tty; 857333347Speter int c, len; 858333347Speter u_char *cp; 859333347Speter 860333347Speter /* 861333347Speter * Loop while there is still input to get from the keyboard. 862333347Speter * I don't think this is nessesary, and it doesn't fix 863333347Speter * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 864333347Speter */ 865333347Speter while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { 866333347Speter 867333347Speter cur_tty = VIRTUAL_TTY(get_scr_num()); 868333347Speter if (!(cur_tty->t_state & TS_ISOPEN)) 869333347Speter if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 870333347Speter continue; 871333347Speter 872333347Speter switch (c & 0xff00) { 873333347Speter case 0x0000: /* normal key */ 874333347Speter (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 875333347Speter break; 876333347Speter case FKEY: /* function key, return string */ 877333347Speter if (cp = get_fstr((u_int)c, (u_int *)&len)) { 878333347Speter while (len-- > 0) 879333347Speter (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 880333347Speter } 881333347Speter break; 882333347Speter case MKEY: /* meta is active, prepend ESC */ 883333347Speter (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 884333347Speter (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 885333347Speter break; 886333347Speter case BKEY: /* backtab fixed sequence (esc [ Z) */ 887333347Speter (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 888333347Speter (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 889333347Speter (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 890333347Speter break; 891333347Speter } 892333347Speter } 893333347Speter 894333347Speter#if 0 895333347Speter if (cur_console->status & MOUSE_ENABLED) { 896333347Speter cur_console->status &= ~MOUSE_VISIBLE; 897333347Speter remove_mouse_image(cur_console); 898333347Speter } 899333347Speter#else 900333347Speter if (cur_console->status & MOUSE_VISIBLE) { 901333347Speter remove_mouse_image(cur_console); 902333347Speter cur_console->status &= ~MOUSE_VISIBLE; 903333347Speter } 904333347Speter#endif 905333347Speter} 906333347Speter 907333347Speterstatic int 908333347Speterscparam(struct tty *tp, struct termios *t) 909333347Speter{ 910333347Speter tp->t_ispeed = t->c_ispeed; 911333347Speter tp->t_ospeed = t->c_ospeed; 912333347Speter tp->t_cflag = t->c_cflag; 913333347Speter return 0; 914333347Speter} 915333347Speter 916333347Speterint 917333347Speterscioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 918333347Speter{ 919333347Speter u_int delta_ehs; 920333347Speter int error; 921333347Speter int i; 922333347Speter struct tty *tp; 923333347Speter scr_stat *scp; 924333347Speter video_adapter_t *adp; 925333347Speter int s; 926333347Speter 927333347Speter tp = scdevtotty(dev); 928333347Speter if (!tp) 929333347Speter return ENXIO; 930333347Speter scp = sc_get_scr_stat(tp->t_dev); 931333347Speter 932333347Speter /* If there is a user_ioctl function call that first */ 933333347Speter if (sc_user_ioctl) { 934333347Speter error = (*sc_user_ioctl)(dev, cmd, data, flag, p); 935333347Speter if (error != ENOIOCTL) 936333347Speter return error; 937333347Speter } 938333347Speter 939333347Speter error = sc_vid_ioctl(tp, cmd, data, flag, p); 940333347Speter if (error != ENOIOCTL) 941333347Speter return error; 942333347Speter 943333347Speter switch (cmd) { /* process console hardware related ioctl's */ 944333347Speter 945333347Speter case GIO_ATTR: /* get current attributes */ 946333347Speter *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 947333347Speter return 0; 948333347Speter 949333347Speter case GIO_COLOR: /* is this a color console ? */ 950333347Speter *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0; 951333347Speter return 0; 952333347Speter 953333347Speter case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 954333347Speter if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) 955333347Speter return EINVAL; 956333347Speter s = spltty(); 957333347Speter scrn_blank_time = *(int *)data; 958333347Speter run_scrn_saver = (scrn_blank_time != 0); 959333347Speter splx(s); 960333347Speter return 0; 961333347Speter 962333347Speter case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 963333347Speter if ((*(int*)data) & 0x01) 964333347Speter sc_flags |= BLINK_CURSOR; 965333347Speter else 966333347Speter sc_flags &= ~BLINK_CURSOR; 967333347Speter if ((*(int*)data) & 0x02) { 968333347Speter if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 969333347Speter return ENXIO; 970333347Speter sc_flags |= CHAR_CURSOR; 971333347Speter } else 972333347Speter sc_flags &= ~CHAR_CURSOR; 973333347Speter /* 974333347Speter * The cursor shape is global property; all virtual consoles 975333347Speter * are affected. Update the cursor in the current console... 976333347Speter */ 977333347Speter if (!ISGRAPHSC(cur_console)) { 978333347Speter remove_cursor_image(cur_console); 979333347Speter if (sc_flags & CHAR_CURSOR) 980333347Speter set_destructive_cursor(cur_console); 981333347Speter draw_cursor_image(cur_console); 982333347Speter } 983333347Speter return 0; 984333347Speter 985333347Speter case CONS_BELLTYPE: /* set bell type sound/visual */ 986333347Speter if ((*(int *)data) & 0x01) 987333347Speter sc_flags |= VISUAL_BELL; 988333347Speter else 989333347Speter sc_flags &= ~VISUAL_BELL; 990333347Speter if ((*(int *)data) & 0x02) 991333347Speter sc_flags |= QUIET_BELL; 992333347Speter else 993333347Speter sc_flags &= ~QUIET_BELL; 994333347Speter return 0; 995333347Speter 996333347Speter case CONS_HISTORY: /* set history size */ 997333347Speter if (*(int *)data > 0) { 998333347Speter int lines; /* buffer size to allocate */ 999333347Speter int lines0; /* current buffer size */ 1000333347Speter 1001333347Speter lines = imax(*(int *)data, scp->ysize); 1002333347Speter lines0 = (scp->history != NULL) ? 1003333347Speter scp->history_size / scp->xsize : scp->ysize; 1004333347Speter if (lines0 > imax(sc_history_size, scp->ysize)) 1005333347Speter delta_ehs = lines0 - imax(sc_history_size, scp->ysize); 1006333347Speter else 1007333347Speter delta_ehs = 0; 1008333347Speter /* 1009333347Speter * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE 1010333347Speter * lines or scp->ysize lines, whichever is larger. A value 1011333347Speter * greater than that is allowed, subject to extra_history_size. 1012333347Speter */ 1013333347Speter if (lines > imax(sc_history_size, scp->ysize)) 1014333347Speter if (lines - imax(sc_history_size, scp->ysize) > 1015333347Speter extra_history_size + delta_ehs) 1016333347Speter return EINVAL; 1017333347Speter if (cur_console->status & BUFFER_SAVED) 1018333347Speter return EBUSY; 1019333347Speter sc_alloc_history_buffer(scp, lines, delta_ehs, TRUE); 1020333347Speter return 0; 1021333347Speter } 1022333347Speter else 1023333347Speter return EINVAL; 1024333347Speter 1025333347Speter case CONS_MOUSECTL: /* control mouse arrow */ 1026333347Speter case OLD_CONS_MOUSECTL: 1027333347Speter { 1028333347Speter /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 1029333347Speter static int butmap[8] = { 1030333347Speter MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1031333347Speter MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1032333347Speter MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 1033333347Speter MOUSE_MSC_BUTTON3UP, 1034333347Speter MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 1035333347Speter MOUSE_MSC_BUTTON2UP, 1036333347Speter MOUSE_MSC_BUTTON1UP, 1037333347Speter 0, 1038333347Speter }; 1039333347Speter mouse_info_t *mouse = (mouse_info_t*)data; 1040333347Speter mouse_info_t buf; 1041333347Speter 1042333347Speter /* FIXME: */ 1043333347Speter if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags)) 1044333347Speter return ENODEV; 1045333347Speter 1046333347Speter if (cmd == OLD_CONS_MOUSECTL) { 1047333347Speter static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 1048333347Speter old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 1049333347Speter 1050333347Speter mouse = &buf; 1051333347Speter mouse->operation = old_mouse->operation; 1052333347Speter switch (mouse->operation) { 1053333347Speter case MOUSE_MODE: 1054333347Speter mouse->u.mode = old_mouse->u.mode; 1055333347Speter break; 1056333347Speter case MOUSE_SHOW: 1057333347Speter case MOUSE_HIDE: 1058333347Speter break; 1059333347Speter case MOUSE_MOVEABS: 1060333347Speter case MOUSE_MOVEREL: 1061333347Speter case MOUSE_ACTION: 1062333347Speter mouse->u.data.x = old_mouse->u.data.x; 1063333347Speter mouse->u.data.y = old_mouse->u.data.y; 1064333347Speter mouse->u.data.z = 0; 1065333347Speter mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 1066333347Speter break; 1067333347Speter case MOUSE_GETINFO: 1068333347Speter old_mouse->u.data.x = scp->mouse_xpos; 1069333347Speter old_mouse->u.data.y = scp->mouse_ypos; 1070333347Speter old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 1071333347Speter break; 1072333347Speter default: 1073333347Speter return EINVAL; 1074333347Speter } 1075333347Speter } 1076333347Speter 1077333347Speter switch (mouse->operation) { 1078333347Speter case MOUSE_MODE: 1079333347Speter if (ISSIGVALID(mouse->u.mode.signal)) { 1080333347Speter scp->mouse_signal = mouse->u.mode.signal; 1081333347Speter scp->mouse_proc = p; 1082333347Speter scp->mouse_pid = p->p_pid; 1083333347Speter } 1084333347Speter else { 1085333347Speter scp->mouse_signal = 0; 1086333347Speter scp->mouse_proc = NULL; 1087333347Speter scp->mouse_pid = 0; 1088333347Speter } 1089333347Speter return 0; 1090333347Speter 1091333347Speter case MOUSE_SHOW: 1092333347Speter if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) { 1093333347Speter scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); 1094333347Speter scp->mouse_oldpos = scp->mouse_pos; 1095333347Speter mark_all(scp); 1096333347Speter return 0; 1097333347Speter } 1098333347Speter else 1099333347Speter return EINVAL; 1100333347Speter break; 1101333347Speter 1102333347Speter case MOUSE_HIDE: 1103333347Speter if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) { 1104333347Speter scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 1105333347Speter mark_all(scp); 1106333347Speter return 0; 1107333347Speter } 1108333347Speter else 1109333347Speter return EINVAL; 1110333347Speter break; 1111333347Speter 1112333347Speter case MOUSE_MOVEABS: 1113333347Speter scp->mouse_xpos = mouse->u.data.x; 1114333347Speter scp->mouse_ypos = mouse->u.data.y; 1115333347Speter set_mouse_pos(scp); 1116333347Speter break; 1117333347Speter 1118333347Speter case MOUSE_MOVEREL: 1119333347Speter scp->mouse_xpos += mouse->u.data.x; 1120333347Speter scp->mouse_ypos += mouse->u.data.y; 1121333347Speter set_mouse_pos(scp); 1122333347Speter break; 1123333347Speter 1124333347Speter case MOUSE_GETINFO: 1125333347Speter mouse->u.data.x = scp->mouse_xpos; 1126333347Speter mouse->u.data.y = scp->mouse_ypos; 1127333347Speter mouse->u.data.z = 0; 1128333347Speter mouse->u.data.buttons = scp->mouse_buttons; 1129333347Speter return 0; 1130333347Speter 1131333347Speter case MOUSE_ACTION: 1132333347Speter case MOUSE_MOTION_EVENT: 1133333347Speter /* this should maybe only be settable from /dev/consolectl SOS */ 1134333347Speter /* send out mouse event on /dev/sysmouse */ 1135333347Speter 1136333347Speter mouse_status.dx += mouse->u.data.x; 1137333347Speter mouse_status.dy += mouse->u.data.y; 1138333347Speter mouse_status.dz += mouse->u.data.z; 1139333347Speter if (mouse->operation == MOUSE_ACTION) 1140333347Speter mouse_status.button = mouse->u.data.buttons; 1141333347Speter mouse_status.flags |= 1142333347Speter ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 1143333347Speter MOUSE_POSCHANGED : 0) 1144333347Speter | (mouse_status.obutton ^ mouse_status.button); 1145333347Speter if (mouse_status.flags == 0) 1146333347Speter return 0; 1147333347Speter 1148333347Speter if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) 1149333347Speter cur_console->status |= MOUSE_VISIBLE; 1150333347Speter 1151333347Speter if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1152333347Speter u_char buf[MOUSE_SYS_PACKETSIZE]; 1153333347Speter int j; 1154333347Speter 1155333347Speter /* the first five bytes are compatible with MouseSystems' */ 1156333347Speter buf[0] = MOUSE_MSC_SYNC 1157333347Speter | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1158333347Speter j = imax(imin(mouse->u.data.x, 255), -256); 1159333347Speter buf[1] = j >> 1; 1160333347Speter buf[3] = j - buf[1]; 1161333347Speter j = -imax(imin(mouse->u.data.y, 255), -256); 1162333347Speter buf[2] = j >> 1; 1163333347Speter buf[4] = j - buf[2]; 1164333347Speter for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) 1165333347Speter (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1166333347Speter if (mouse_level >= 1) { /* extended part */ 1167333347Speter j = imax(imin(mouse->u.data.z, 127), -128); 1168333347Speter buf[5] = (j >> 1) & 0x7f; 1169333347Speter buf[6] = (j - (j >> 1)) & 0x7f; 1170333347Speter /* buttons 4-10 */ 1171333347Speter buf[7] = (~mouse_status.button >> 3) & 0x7f; 1172333347Speter for (j = MOUSE_MSC_PACKETSIZE; 1173333347Speter j < MOUSE_SYS_PACKETSIZE; j++) 1174333347Speter (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1175333347Speter } 1176333347Speter } 1177333347Speter 1178333347Speter if (cur_console->mouse_signal) { 1179333347Speter cur_console->mouse_buttons = mouse->u.data.buttons; 1180333347Speter /* has controlling process died? */ 1181333347Speter if (cur_console->mouse_proc && 1182333347Speter (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1183333347Speter cur_console->mouse_signal = 0; 1184333347Speter cur_console->mouse_proc = NULL; 1185333347Speter cur_console->mouse_pid = 0; 1186333347Speter } 1187333347Speter else 1188333347Speter psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1189333347Speter } 1190333347Speter else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) { 1191333347Speter /* process button presses */ 1192333347Speter if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 1193333347Speter ISTEXTSC(cur_console)) { 1194333347Speter cur_console->mouse_buttons = mouse->u.data.buttons; 1195333347Speter if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) 1196333347Speter mouse_cut_start(cur_console); 1197333347Speter else 1198333347Speter mouse_cut_end(cur_console); 1199333347Speter if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || 1200333347Speter cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) 1201333347Speter mouse_paste(cur_console); 1202333347Speter } 1203333347Speter } 1204333347Speter 1205333347Speter if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 1206333347Speter cur_console->mouse_xpos += mouse->u.data.x; 1207333347Speter cur_console->mouse_ypos += mouse->u.data.y; 1208333347Speter set_mouse_pos(cur_console); 1209333347Speter } 1210333347Speter 1211333347Speter break; 1212333347Speter 1213333347Speter case MOUSE_BUTTON_EVENT: 1214333347Speter if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 1215333347Speter return EINVAL; 1216333347Speter if (mouse->u.event.value < 0) 1217333347Speter return EINVAL; 1218333347Speter 1219333347Speter if (mouse->u.event.value > 0) { 1220333347Speter cur_console->mouse_buttons |= mouse->u.event.id; 1221333347Speter mouse_status.button |= mouse->u.event.id; 1222333347Speter } else { 1223333347Speter cur_console->mouse_buttons &= ~mouse->u.event.id; 1224333347Speter mouse_status.button &= ~mouse->u.event.id; 1225333347Speter } 1226333347Speter mouse_status.flags |= mouse_status.obutton ^ mouse_status.button; 1227333347Speter if (mouse_status.flags == 0) 1228333347Speter return 0; 1229333347Speter 1230333347Speter if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) 1231333347Speter cur_console->status |= MOUSE_VISIBLE; 1232333347Speter 1233333347Speter if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1234333347Speter u_char buf[8]; 1235333347Speter int i; 1236333347Speter 1237333347Speter buf[0] = MOUSE_MSC_SYNC 1238333347Speter | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1239333347Speter buf[7] = (~mouse_status.button >> 3) & 0x7f; 1240333347Speter buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 1241333347Speter for (i = 0; 1242333347Speter i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 1243333347Speter : MOUSE_MSC_PACKETSIZE); i++) 1244333347Speter (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); 1245333347Speter } 1246333347Speter 1247333347Speter if (cur_console->mouse_signal) { 1248333347Speter if (cur_console->mouse_proc && 1249333347Speter (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1250333347Speter cur_console->mouse_signal = 0; 1251333347Speter cur_console->mouse_proc = NULL; 1252333347Speter cur_console->mouse_pid = 0; 1253333347Speter } 1254333347Speter else 1255333347Speter psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1256333347Speter break; 1257333347Speter } 1258333347Speter 1259333347Speter if (!ISTEXTSC(cur_console) || (cut_buffer == NULL)) 1260333347Speter break; 1261333347Speter 1262333347Speter switch (mouse->u.event.id) { 1263333347Speter case MOUSE_BUTTON1DOWN: 1264333347Speter switch (mouse->u.event.value % 4) { 1265333347Speter case 0: /* up */ 1266333347Speter mouse_cut_end(cur_console); 1267333347Speter break; 1268333347Speter case 1: 1269333347Speter mouse_cut_start(cur_console); 1270333347Speter break; 1271333347Speter case 2: 1272333347Speter mouse_cut_word(cur_console); 1273333347Speter break; 1274333347Speter case 3: 1275333347Speter mouse_cut_line(cur_console); 1276333347Speter break; 1277333347Speter } 1278333347Speter break; 1279333347Speter case MOUSE_BUTTON2DOWN: 1280333347Speter switch (mouse->u.event.value) { 1281333347Speter case 0: /* up */ 1282333347Speter break; 1283333347Speter default: 1284333347Speter mouse_paste(cur_console); 1285333347Speter break; 1286333347Speter } 1287333347Speter break; 1288333347Speter case MOUSE_BUTTON3DOWN: 1289333347Speter switch (mouse->u.event.value) { 1290333347Speter case 0: /* up */ 1291333347Speter if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) 1292333347Speter mouse_cut_end(cur_console); 1293333347Speter break; 1294333347Speter default: 1295333347Speter mouse_cut_extend(cur_console); 1296333347Speter break; 1297333347Speter } 1298333347Speter break; 1299333347Speter } 1300333347Speter break; 1301333347Speter 1302333347Speter default: 1303333347Speter return EINVAL; 1304333347Speter } 1305333347Speter /* make screensaver happy */ 1306333347Speter scsplash_stick(FALSE); 1307333347Speter run_scrn_saver = FALSE; 1308333347Speter return 0; 1309333347Speter } 1310333347Speter 1311333347Speter /* MOUSE_XXX: /dev/sysmouse ioctls */ 1312333347Speter case MOUSE_GETHWINFO: /* get device information */ 1313333347Speter { 1314333347Speter mousehw_t *hw = (mousehw_t *)data; 1315333347Speter 1316333347Speter if (tp != MOUSE_TTY) 1317333347Speter return ENOTTY; 1318333347Speter hw->buttons = 10; /* XXX unknown */ 1319333347Speter hw->iftype = MOUSE_IF_SYSMOUSE; 1320333347Speter hw->type = MOUSE_MOUSE; 1321333347Speter hw->model = MOUSE_MODEL_GENERIC; 1322333347Speter hw->hwid = 0; 1323333347Speter return 0; 1324333347Speter } 1325333347Speter 1326333347Speter case MOUSE_GETMODE: /* get protocol/mode */ 1327333347Speter { 1328333347Speter mousemode_t *mode = (mousemode_t *)data; 1329333347Speter 1330333347Speter if (tp != MOUSE_TTY) 1331333347Speter return ENOTTY; 1332333347Speter mode->level = mouse_level; 1333333347Speter switch (mode->level) { 1334333347Speter case 0: 1335333347Speter /* at this level, sysmouse emulates MouseSystems protocol */ 1336333347Speter mode->protocol = MOUSE_PROTO_MSC; 1337333347Speter mode->rate = -1; /* unknown */ 1338333347Speter mode->resolution = -1; /* unknown */ 1339333347Speter mode->accelfactor = 0; /* disabled */ 1340333347Speter mode->packetsize = MOUSE_MSC_PACKETSIZE; 1341333347Speter mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 1342333347Speter mode->syncmask[1] = MOUSE_MSC_SYNC; 1343333347Speter break; 1344333347Speter 1345333347Speter case 1: 1346333347Speter /* at this level, sysmouse uses its own protocol */ 1347333347Speter mode->protocol = MOUSE_PROTO_SYSMOUSE; 1348333347Speter mode->rate = -1; 1349333347Speter mode->resolution = -1; 1350333347Speter mode->accelfactor = 0; 1351333347Speter mode->packetsize = MOUSE_SYS_PACKETSIZE; 1352333347Speter mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 1353333347Speter mode->syncmask[1] = MOUSE_SYS_SYNC; 1354333347Speter break; 1355333347Speter } 1356333347Speter return 0; 1357333347Speter } 1358333347Speter 1359333347Speter case MOUSE_SETMODE: /* set protocol/mode */ 1360333347Speter { 1361333347Speter mousemode_t *mode = (mousemode_t *)data; 1362333347Speter 1363333347Speter if (tp != MOUSE_TTY) 1364333347Speter return ENOTTY; 1365333347Speter if ((mode->level < 0) || (mode->level > 1)) 1366333347Speter return EINVAL; 1367333347Speter mouse_level = mode->level; 1368333347Speter return 0; 1369333347Speter } 1370333347Speter 1371333347Speter case MOUSE_GETLEVEL: /* get operation level */ 1372333347Speter if (tp != MOUSE_TTY) 1373333347Speter return ENOTTY; 1374333347Speter *(int *)data = mouse_level; 1375333347Speter return 0; 1376333347Speter 1377333347Speter case MOUSE_SETLEVEL: /* set operation level */ 1378333347Speter if (tp != MOUSE_TTY) 1379333347Speter return ENOTTY; 1380333347Speter if ((*(int *)data < 0) || (*(int *)data > 1)) 1381333347Speter return EINVAL; 1382333347Speter mouse_level = *(int *)data; 1383333347Speter return 0; 1384333347Speter 1385333347Speter case MOUSE_GETSTATUS: /* get accumulated mouse events */ 1386333347Speter if (tp != MOUSE_TTY) 1387333347Speter return ENOTTY; 1388333347Speter s = spltty(); 1389333347Speter *(mousestatus_t *)data = mouse_status; 1390333347Speter mouse_status.flags = 0; 1391333347Speter mouse_status.obutton = mouse_status.button; 1392333347Speter mouse_status.dx = 0; 1393333347Speter mouse_status.dy = 0; 1394333347Speter mouse_status.dz = 0; 1395333347Speter splx(s); 1396333347Speter return 0; 1397333347Speter 1398333347Speter#if notyet 1399333347Speter case MOUSE_GETVARS: /* get internal mouse variables */ 1400333347Speter case MOUSE_SETVARS: /* set internal mouse variables */ 1401333347Speter if (tp != MOUSE_TTY) 1402333347Speter return ENOTTY; 1403333347Speter return ENODEV; 1404333347Speter#endif 1405333347Speter 1406333347Speter case MOUSE_READSTATE: /* read status from the device */ 1407333347Speter case MOUSE_READDATA: /* read data from the device */ 1408333347Speter if (tp != MOUSE_TTY) 1409333347Speter return ENOTTY; 1410333347Speter return ENODEV; 1411333347Speter 1412333347Speter case CONS_GETINFO: /* get current (virtual) console info */ 1413333347Speter { 1414333347Speter vid_info_t *ptr = (vid_info_t*)data; 1415333347Speter if (ptr->size == sizeof(struct vid_info)) { 1416333347Speter ptr->m_num = get_scr_num(); 1417333347Speter ptr->mv_col = scp->xpos; 1418333347Speter ptr->mv_row = scp->ypos; 1419333347Speter ptr->mv_csz = scp->xsize; 1420333347Speter ptr->mv_rsz = scp->ysize; 1421333347Speter ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 1422333347Speter ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 1423333347Speter ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 1424333347Speter ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 1425333347Speter ptr->mv_grfc.fore = 0; /* not supported */ 1426333347Speter ptr->mv_grfc.back = 0; /* not supported */ 1427333347Speter ptr->mv_ovscan = scp->border; 1428333347Speter ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 1429333347Speter return 0; 1430333347Speter } 1431333347Speter return EINVAL; 1432333347Speter } 1433333347Speter 1434333347Speter case CONS_GETVERS: /* get version number */ 1435333347Speter *(int*)data = 0x200; /* version 2.0 */ 1436333347Speter return 0; 1437333347Speter 1438333347Speter case CONS_IDLE: /* see if the screen has been idle */ 1439333347Speter /* 1440333347Speter * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE, 1441333347Speter * the user process may have been writing something on the 1442333347Speter * screen and syscons is not aware of it. Declare the screen 1443333347Speter * is NOT idle if it is in one of these modes. But there is 1444333347Speter * an exception to it; if a screen saver is running in the 1445333347Speter * graphics mode in the current screen, we should say that the 1446333347Speter * screen has been idle. 1447333347Speter */ 1448333347Speter *(int *)data = scrn_idle 1449333347Speter && (!ISGRAPHSC(cur_console) 1450333347Speter || (cur_console->status & SAVER_RUNNING)); 1451333347Speter return 0; 1452333347Speter 1453333347Speter case CONS_SAVERMODE: /* set saver mode */ 1454333347Speter switch(*(int *)data) { 1455333347Speter case CONS_USR_SAVER: 1456333347Speter /* if a LKM screen saver is running, stop it first. */ 1457333347Speter scsplash_stick(FALSE); 1458333347Speter saver_mode = *(int *)data; 1459333347Speter s = spltty(); 1460333347Speter if ((error = wait_scrn_saver_stop())) { 1461333347Speter splx(s); 1462333347Speter return error; 1463333347Speter } 1464333347Speter scp->status |= SAVER_RUNNING; 1465333347Speter scsplash_stick(TRUE); 1466333347Speter splx(s); 1467333347Speter break; 1468333347Speter case CONS_LKM_SAVER: 1469333347Speter s = spltty(); 1470333347Speter if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING)) 1471333347Speter scp->status &= ~SAVER_RUNNING; 1472333347Speter saver_mode = *(int *)data; 1473333347Speter splx(s); 1474333347Speter break; 1475333347Speter default: 1476333347Speter return EINVAL; 1477333347Speter } 1478333347Speter return 0; 1479333347Speter 1480333347Speter case CONS_SAVERSTART: /* immediately start/stop the screen saver */ 1481333347Speter /* 1482 * Note that this ioctl does not guarantee the screen saver 1483 * actually starts or stops. It merely attempts to do so... 1484 */ 1485 s = spltty(); 1486 run_scrn_saver = (*(int *)data != 0); 1487 if (run_scrn_saver) 1488 scrn_time_stamp -= scrn_blank_time; 1489 splx(s); 1490 return 0; 1491 1492 case VT_SETMODE: /* set screen switcher mode */ 1493 { 1494 struct vt_mode *mode; 1495 1496 mode = (struct vt_mode *)data; 1497 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && 1498 ISSIGVALID(mode->frsig)) { 1499 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 1500 if (scp->smode.mode == VT_PROCESS) { 1501 scp->proc = p; 1502 scp->pid = scp->proc->p_pid; 1503 } 1504 return 0; 1505 } else 1506 return EINVAL; 1507 } 1508 1509 case VT_GETMODE: /* get screen switcher mode */ 1510 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 1511 return 0; 1512 1513 case VT_RELDISP: /* screen switcher ioctl */ 1514 switch(*(int *)data) { 1515 case VT_FALSE: /* user refuses to release screen, abort */ 1516 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1517 old_scp->status &= ~SWITCH_WAIT_REL; 1518 switch_in_progress = FALSE; 1519 return 0; 1520 } 1521 return EINVAL; 1522 1523 case VT_TRUE: /* user has released screen, go on */ 1524 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1525 scp->status &= ~SWITCH_WAIT_REL; 1526 exchange_scr(); 1527 if (new_scp->smode.mode == VT_PROCESS) { 1528 new_scp->status |= SWITCH_WAIT_ACQ; 1529 psignal(new_scp->proc, new_scp->smode.acqsig); 1530 } 1531 else 1532 switch_in_progress = FALSE; 1533 return 0; 1534 } 1535 return EINVAL; 1536 1537 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 1538 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 1539 scp->status &= ~SWITCH_WAIT_ACQ; 1540 switch_in_progress = FALSE; 1541 return 0; 1542 } 1543 return EINVAL; 1544 1545 default: 1546 return EINVAL; 1547 } 1548 /* NOT REACHED */ 1549 1550 case VT_OPENQRY: /* return free virtual console */ 1551 for (i = 0; i < MAXCONS; i++) { 1552 tp = VIRTUAL_TTY(i); 1553 if (!(tp->t_state & TS_ISOPEN)) { 1554 *(int *)data = i + 1; 1555 return 0; 1556 } 1557 } 1558 return EINVAL; 1559 1560 case VT_ACTIVATE: /* switch to screen *data */ 1561 return switch_scr(scp, *(int *)data - 1); 1562 1563 case VT_WAITACTIVE: /* wait for switch to occur */ 1564 if (*(int *)data > MAXCONS || *(int *)data < 0) 1565 return EINVAL; 1566 if (minor(dev) == *(int *)data - 1) 1567 return 0; 1568 if (*(int *)data == 0) { 1569 if (scp == cur_console) 1570 return 0; 1571 } 1572 else 1573 scp = console[*(int *)data - 1]; 1574 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1575 "waitvt", 0)) == ERESTART) ; 1576 return error; 1577 1578 case VT_GETACTIVE: 1579 *(int *)data = get_scr_num()+1; 1580 return 0; 1581 1582 case KDENABIO: /* allow io operations */ 1583 error = suser(p->p_ucred, &p->p_acflag); 1584 if (error != 0) 1585 return error; 1586 if (securelevel > 0) 1587 return EPERM; 1588 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 1589 return 0; 1590 1591 case KDDISABIO: /* disallow io operations (default) */ 1592 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 1593 return 0; 1594 1595 case KDSKBSTATE: /* set keyboard state (locks) */ 1596 if (*(int *)data & ~LOCK_KEY_MASK) 1597 return EINVAL; 1598 scp->status &= ~LOCK_KEY_MASK; 1599 scp->status |= *(int *)data; 1600 if (scp == cur_console) 1601 update_leds(scp->status); 1602 return 0; 1603 1604 case KDGKBSTATE: /* get keyboard state (locks) */ 1605 *(int *)data = scp->status & LOCK_KEY_MASK; 1606 return 0; 1607 1608 case KDSETRAD: /* set keyboard repeat & delay rates */ 1609 if (*(int *)data & ~0x7f) 1610 return EINVAL; 1611 if (sc_kbdc != NULL) 1612 set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data); 1613 return 0; 1614 1615 case KDSKBMODE: /* set keyboard mode */ 1616 switch (*(int *)data) { 1617 case K_RAW: /* switch to RAW scancode mode */ 1618 scp->status &= ~KBD_CODE_MODE; 1619 scp->status |= KBD_RAW_MODE; 1620 return 0; 1621 1622 case K_CODE: /* switch to CODE mode */ 1623 scp->status &= ~KBD_RAW_MODE; 1624 scp->status |= KBD_CODE_MODE; 1625 return 0; 1626 1627 case K_XLATE: /* switch to XLT ascii mode */ 1628 if (scp == cur_console && scp->status & KBD_RAW_MODE) 1629 shfts = ctls = alts = agrs = metas = accents = 0; 1630 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); 1631 return 0; 1632 default: 1633 return EINVAL; 1634 } 1635 /* NOT REACHED */ 1636 1637 case KDGKBMODE: /* get keyboard mode */ 1638 *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : 1639 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); 1640 return 0; 1641 1642 case KDMKTONE: /* sound the bell */ 1643 if (*(int*)data) 1644 do_bell(scp, (*(int*)data)&0xffff, 1645 (((*(int*)data)>>16)&0xffff)*hz/1000); 1646 else 1647 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1648 return 0; 1649 1650 case KIOCSOUND: /* make tone (*data) hz */ 1651 if (scp == cur_console) { 1652 if (*(int*)data) { 1653 int pitch = timer_freq / *(int*)data; 1654 1655 /* set command for counter 2, 2 byte write */ 1656 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1657 return EBUSY; 1658 1659 /* set pitch */ 1660 outb(TIMER_CNTR2, pitch); 1661 outb(TIMER_CNTR2, (pitch>>8)); 1662 1663 /* enable counter 2 output to speaker */ 1664 outb(IO_PPI, inb(IO_PPI) | 3); 1665 } 1666 else { 1667 /* disable counter 2 output to speaker */ 1668 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1669 release_timer2(); 1670 } 1671 } 1672 return 0; 1673 1674 case KDGKBTYPE: /* get keyboard type */ 1675 *(int *)data = 0; /* type not known (yet) */ 1676 return 0; 1677 1678 case KDSETLED: /* set keyboard LED status */ 1679 if (*(int *)data & ~LED_MASK) 1680 return EINVAL; 1681 scp->status &= ~LED_MASK; 1682 scp->status |= *(int *)data; 1683 if (scp == cur_console) 1684 update_leds(scp->status); 1685 return 0; 1686 1687 case KDGETLED: /* get keyboard LED status */ 1688 *(int *)data = scp->status & LED_MASK; 1689 return 0; 1690 1691 case GETFKEY: /* get functionkey string */ 1692 if (*(u_short*)data < n_fkey_tab) { 1693 fkeyarg_t *ptr = (fkeyarg_t*)data; 1694 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1695 fkey_tab[ptr->keynum].len); 1696 ptr->flen = fkey_tab[ptr->keynum].len; 1697 return 0; 1698 } 1699 else 1700 return EINVAL; 1701 1702 case SETFKEY: /* set functionkey string */ 1703 if (*(u_short*)data < n_fkey_tab) { 1704 fkeyarg_t *ptr = (fkeyarg_t*)data; 1705 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1706 min(ptr->flen, MAXFK)); 1707 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1708 return 0; 1709 } 1710 else 1711 return EINVAL; 1712 1713 case GIO_SCRNMAP: /* get output translation table */ 1714 bcopy(&scr_map, data, sizeof(scr_map)); 1715 return 0; 1716 1717 case PIO_SCRNMAP: /* set output translation table */ 1718 bcopy(data, &scr_map, sizeof(scr_map)); 1719 for (i=0; i<sizeof(scr_map); i++) 1720 scr_rmap[scr_map[i]] = i; 1721 return 0; 1722 1723 case GIO_KEYMAP: /* get keyboard translation table */ 1724 bcopy(&key_map, data, sizeof(key_map)); 1725 return 0; 1726 1727 case PIO_KEYMAP: /* set keyboard translation table */ 1728 accents = 0; 1729 bzero(&accent_map, sizeof(accent_map)); 1730 bcopy(data, &key_map, sizeof(key_map)); 1731 return 0; 1732 1733 case GIO_DEADKEYMAP: /* get accent key translation table */ 1734 bcopy(&accent_map, data, sizeof(accent_map)); 1735 return 0; 1736 1737 case PIO_DEADKEYMAP: /* set accent key translation table */ 1738 accents = 0; 1739 bcopy(data, &accent_map, sizeof(accent_map)); 1740 return 0; 1741 1742 case PIO_FONT8x8: /* set 8x8 dot font */ 1743 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1744 return ENXIO; 1745 bcopy(data, font_8, 8*256); 1746 fonts_loaded |= FONT_8; 1747 /* 1748 * FONT KLUDGE 1749 * Always use the font page #0. XXX 1750 * Don't load if the current font size is not 8x8. 1751 */ 1752 if (ISTEXTSC(cur_console) && (cur_console->font_size < 14)) 1753 copy_font(cur_console, LOAD, 8, font_8); 1754 return 0; 1755 1756 case GIO_FONT8x8: /* get 8x8 dot font */ 1757 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1758 return ENXIO; 1759 if (fonts_loaded & FONT_8) { 1760 bcopy(font_8, data, 8*256); 1761 return 0; 1762 } 1763 else 1764 return ENXIO; 1765 1766 case PIO_FONT8x14: /* set 8x14 dot font */ 1767 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1768 return ENXIO; 1769 bcopy(data, font_14, 14*256); 1770 fonts_loaded |= FONT_14; 1771 /* 1772 * FONT KLUDGE 1773 * Always use the font page #0. XXX 1774 * Don't load if the current font size is not 8x14. 1775 */ 1776 if (ISTEXTSC(cur_console) 1777 && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) 1778 copy_font(cur_console, LOAD, 14, font_14); 1779 return 0; 1780 1781 case GIO_FONT8x14: /* get 8x14 dot font */ 1782 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1783 return ENXIO; 1784 if (fonts_loaded & FONT_14) { 1785 bcopy(font_14, data, 14*256); 1786 return 0; 1787 } 1788 else 1789 return ENXIO; 1790 1791 case PIO_FONT8x16: /* set 8x16 dot font */ 1792 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1793 return ENXIO; 1794 bcopy(data, font_16, 16*256); 1795 fonts_loaded |= FONT_16; 1796 /* 1797 * FONT KLUDGE 1798 * Always use the font page #0. XXX 1799 * Don't load if the current font size is not 8x16. 1800 */ 1801 if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16)) 1802 copy_font(cur_console, LOAD, 16, font_16); 1803 return 0; 1804 1805 case GIO_FONT8x16: /* get 8x16 dot font */ 1806 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1807 return ENXIO; 1808 if (fonts_loaded & FONT_16) { 1809 bcopy(font_16, data, 16*256); 1810 return 0; 1811 } 1812 else 1813 return ENXIO; 1814 default: 1815 break; 1816 } 1817 1818 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1819 if (error != ENOIOCTL) 1820 return(error); 1821 error = ttioctl(tp, cmd, data, flag); 1822 if (error != ENOIOCTL) 1823 return(error); 1824 return(ENOTTY); 1825} 1826 1827static void 1828scstart(struct tty *tp) 1829{ 1830 struct clist *rbp; 1831 int s, len; 1832 u_char buf[PCBURST]; 1833 scr_stat *scp = sc_get_scr_stat(tp->t_dev); 1834 1835 if (scp->status & SLKED || blink_in_progress) 1836 return; /* XXX who repeats the call when the above flags are cleared? */ 1837 s = spltty(); 1838 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1839 tp->t_state |= TS_BUSY; 1840 rbp = &tp->t_outq; 1841 while (rbp->c_cc) { 1842 len = q_to_b(rbp, buf, PCBURST); 1843 splx(s); 1844 ansi_put(scp, buf, len); 1845 s = spltty(); 1846 } 1847 tp->t_state &= ~TS_BUSY; 1848 ttwwakeup(tp); 1849 } 1850 splx(s); 1851} 1852 1853static void 1854scmousestart(struct tty *tp) 1855{ 1856 struct clist *rbp; 1857 int s; 1858 u_char buf[PCBURST]; 1859 1860 s = spltty(); 1861 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1862 tp->t_state |= TS_BUSY; 1863 rbp = &tp->t_outq; 1864 while (rbp->c_cc) { 1865 q_to_b(rbp, buf, PCBURST); 1866 } 1867 tp->t_state &= ~TS_BUSY; 1868 ttwwakeup(tp); 1869 } 1870 splx(s); 1871} 1872 1873void 1874sccnprobe(struct consdev *cp) 1875{ 1876 struct isa_device *dvp; 1877 1878 /* 1879 * Take control if we are the highest priority enabled display device. 1880 */ 1881 dvp = find_display(); 1882 if (dvp == NULL || dvp->id_driver != &scdriver) { 1883 cp->cn_pri = CN_DEAD; 1884 return; 1885 } 1886 1887 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { 1888 cp->cn_pri = CN_DEAD; 1889 return; 1890 } 1891 1892 /* initialize required fields */ 1893 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 1894 cp->cn_pri = CN_INTERNAL; 1895 1896 sc_kbdc = kbdc_open(sc_port); 1897} 1898 1899void 1900sccninit(struct consdev *cp) 1901{ 1902 scinit(); 1903} 1904 1905void 1906sccnputc(dev_t dev, int c) 1907{ 1908 u_char buf[1]; 1909 int s; 1910 scr_stat *scp = console[0]; 1911 term_stat save = scp->term; 1912 1913 scp->term = kernel_console; 1914 current_default = &kernel_default; 1915 if (scp == cur_console && !ISGRAPHSC(scp)) 1916 remove_cursor_image(scp); 1917 buf[0] = c; 1918 ansi_put(scp, buf, 1); 1919 kernel_console = scp->term; 1920 current_default = &user_default; 1921 scp->term = save; 1922 1923 s = spltty(); /* block scintr and scrn_timer */ 1924 sccnupdate(scp); 1925 splx(s); 1926} 1927 1928int 1929sccngetc(dev_t dev) 1930{ 1931 int s = spltty(); /* block scintr and scrn_timer while we poll */ 1932 int c; 1933 1934 /* 1935 * Stop the screen saver and update the screen if necessary. 1936 * What if we have been running in the screen saver code... XXX 1937 */ 1938 scsplash_stick(FALSE); 1939 run_scrn_saver = FALSE; 1940 sccnupdate(cur_console); 1941 1942 c = scgetc(SCGETC_CN); 1943 splx(s); 1944 return(c); 1945} 1946 1947int 1948sccncheckc(dev_t dev) 1949{ 1950 int s = spltty(); /* block scintr and scrn_timer while we poll */ 1951 int c; 1952 1953 scsplash_stick(FALSE); 1954 run_scrn_saver = FALSE; 1955 sccnupdate(cur_console); 1956 1957 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); 1958 splx(s); 1959 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ 1960} 1961 1962static void 1963sccnupdate(scr_stat *scp) 1964{ 1965 /* this is a cut-down version of scrn_timer()... */ 1966 1967 if (font_loading_in_progress) 1968 return; 1969 1970 if (panicstr || shutdown_in_progress) { 1971 scsplash_stick(FALSE); 1972 run_scrn_saver = FALSE; 1973 } else if (scp != cur_console) { 1974 return; 1975 } 1976 1977 if (!run_scrn_saver) 1978 scrn_idle = FALSE; 1979 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 1980 if (scp->status & SAVER_RUNNING) 1981 stop_scrn_saver(current_saver); 1982 1983 if (scp != cur_console || blink_in_progress || switch_in_progress) 1984 return; 1985 1986 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 1987 scrn_update(scp, TRUE); 1988} 1989 1990scr_stat 1991*sc_get_scr_stat(dev_t dev) 1992{ 1993 int unit = minor(dev); 1994 1995 if (unit == SC_CONSOLE) 1996 return console[0]; 1997 if (unit >= MAXCONS || unit < 0) 1998 return(NULL); 1999 return console[unit]; 2000} 2001 2002static int 2003get_scr_num() 2004{ 2005 int i = 0; 2006 2007 while ((i < MAXCONS) && (cur_console != console[i])) 2008 i++; 2009 return i < MAXCONS ? i : 0; 2010} 2011 2012static void 2013scrn_timer(void *arg) 2014{ 2015 struct timeval tv; 2016 scr_stat *scp; 2017 int s; 2018 2019 /* don't do anything when we are touching font */ 2020 if (font_loading_in_progress) { 2021 if (arg) 2022 timeout(scrn_timer, (void *)TRUE, hz / 10); 2023 return; 2024 } 2025 s = spltty(); 2026 2027 /* 2028 * With release 2.1 of the Xaccel server, the keyboard is left 2029 * hanging pretty often. Apparently an interrupt from the 2030 * keyboard is lost, and I don't know why (yet). 2031 * This ugly hack calls scintr if input is ready for the keyboard 2032 * and conveniently hides the problem. XXX 2033 */ 2034 /* Try removing anything stuck in the keyboard controller; whether 2035 * it's a keyboard scan code or mouse data. `scintr()' doesn't 2036 * read the mouse data directly, but `kbdio' routines will, as a 2037 * side effect. 2038 */ 2039 if (kbdc_lock(sc_kbdc, TRUE)) { 2040 /* 2041 * We have seen the lock flag is not set. Let's reset the flag early; 2042 * otherwise `update_led()' failes which may want the lock 2043 * during `scintr()'. 2044 */ 2045 kbdc_lock(sc_kbdc, FALSE); 2046 if (kbdc_data_ready(sc_kbdc)) 2047 scintr(0); 2048 } 2049 2050 scp = cur_console; 2051 2052 /* should we stop the screen saver? */ 2053 getmicrouptime(&tv); 2054 if (panicstr || shutdown_in_progress) { 2055 scsplash_stick(FALSE); 2056 run_scrn_saver = FALSE; 2057 } 2058 if (run_scrn_saver) { 2059 scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time); 2060 } else { 2061 scrn_time_stamp = tv.tv_sec; 2062 scrn_idle = FALSE; 2063 if (scrn_blank_time > 0) 2064 run_scrn_saver = TRUE; 2065 } 2066 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 2067 if (scp->status & SAVER_RUNNING) 2068 stop_scrn_saver(current_saver); 2069 2070 /* should we just return ? */ 2071 if (blink_in_progress || switch_in_progress) { 2072 if (arg) 2073 timeout(scrn_timer, (void *)TRUE, hz / 10); 2074 splx(s); 2075 return; 2076 } 2077 2078 /* Update the screen */ 2079 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 2080 scrn_update(scp, TRUE); 2081 2082 /* should we activate the screen saver? */ 2083 if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) 2084 if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING)) 2085 scrn_saver(current_saver, TRUE); 2086 2087 if (arg) 2088 timeout(scrn_timer, (void *)TRUE, hz / 25); 2089 splx(s); 2090} 2091 2092static void 2093scrn_update(scr_stat *scp, int show_cursor) 2094{ 2095 /* update screen image */ 2096 if (scp->start <= scp->end) 2097 sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0); 2098 2099 /* we are not to show the cursor and the mouse pointer... */ 2100 if (!show_cursor) { 2101 scp->end = 0; 2102 scp->start = scp->xsize*scp->ysize - 1; 2103 return; 2104 } 2105 2106 /* update "pseudo" mouse pointer image */ 2107 if (scp->status & MOUSE_VISIBLE) { 2108 /* did mouse move since last time ? */ 2109 if (scp->status & MOUSE_MOVED) { 2110 /* do we need to remove old mouse pointer image ? */ 2111 if (scp->mouse_cut_start != NULL || 2112 (scp->mouse_pos-scp->scr_buf) <= scp->start || 2113 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) { 2114 remove_mouse_image(scp); 2115 } 2116 scp->status &= ~MOUSE_MOVED; 2117 draw_mouse_image(scp); 2118 } 2119 else { 2120 /* mouse didn't move, has it been overwritten ? */ 2121 if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start && 2122 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 2123 draw_mouse_image(scp); 2124 } 2125 } 2126 } 2127 2128 /* update cursor image */ 2129 if (scp->status & CURSOR_ENABLED) { 2130 /* did cursor move since last time ? */ 2131 if (scp->cursor_pos != scp->cursor_oldpos) { 2132 /* do we need to remove old cursor image ? */ 2133 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 2134 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 2135 remove_cursor_image(scp); 2136 } 2137 scp->cursor_oldpos = scp->cursor_pos; 2138 draw_cursor_image(scp); 2139 } 2140 else { 2141 /* cursor didn't move, has it been overwritten ? */ 2142 if (scp->cursor_pos - scp->scr_buf >= scp->start && 2143 scp->cursor_pos - scp->scr_buf <= scp->end) { 2144 draw_cursor_image(scp); 2145 } else { 2146 /* if its a blinking cursor, we may have to update it */ 2147 if (sc_flags & BLINK_CURSOR) 2148 draw_cursor_image(scp); 2149 } 2150 } 2151 blinkrate++; 2152 } 2153 2154 if (scp->mouse_cut_start != NULL) 2155 draw_cutmarking(scp); 2156 2157 scp->end = 0; 2158 scp->start = scp->xsize*scp->ysize - 1; 2159} 2160 2161int 2162add_scrn_saver(void (*this_saver)(int)) 2163{ 2164#ifdef SC_SPLASH_SCREEN 2165 if (current_saver == scsplash) { 2166 scsplash_stick(FALSE); 2167 stop_scrn_saver(scsplash); 2168 } 2169#endif 2170 2171 if (current_saver != default_saver) 2172 return EBUSY; 2173 run_scrn_saver = FALSE; 2174 saver_mode = CONS_LKM_SAVER; 2175 current_saver = this_saver; 2176 return 0; 2177} 2178 2179int 2180remove_scrn_saver(void (*this_saver)(int)) 2181{ 2182 if (current_saver != this_saver) 2183 return EINVAL; 2184 2185 /* 2186 * In order to prevent `current_saver' from being called by 2187 * the timeout routine `scrn_timer()' while we manipulate 2188 * the saver list, we shall set `current_saver' to `none_saver' 2189 * before stopping the current saver, rather than blocking by `splXX()'. 2190 */ 2191 current_saver = none_saver; 2192 if (scrn_blanked > 0) 2193 stop_scrn_saver(this_saver); 2194 2195 if (scrn_blanked > 0) 2196 return EBUSY; /* XXX */ 2197 2198 current_saver = default_saver; 2199 return 0; 2200} 2201 2202static void 2203scrn_saver(void (*saver)(int), int blank) 2204{ 2205 static int busy = FALSE; 2206 2207 if (busy) 2208 return; 2209 busy = TRUE; 2210 (*saver)(blank); 2211 busy = FALSE; 2212} 2213 2214static void 2215stop_scrn_saver(void (*saver)(int)) 2216{ 2217 scrn_saver(saver, FALSE); 2218 run_scrn_saver = FALSE; 2219 /* the screen saver may have chosen not to stop after all... */ 2220 if (scrn_blanked > 0) 2221 return; 2222 2223 mark_all(cur_console); 2224 if (delayed_next_scr) 2225 switch_scr(cur_console, delayed_next_scr - 1); 2226 wakeup((caddr_t)&scrn_blanked); 2227} 2228 2229static int 2230wait_scrn_saver_stop(void) 2231{ 2232 int error = 0; 2233 2234 while (scrn_blanked > 0) { 2235 run_scrn_saver = FALSE; 2236 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); 2237 run_scrn_saver = FALSE; 2238 if (error != ERESTART) 2239 break; 2240 } 2241 return error; 2242} 2243 2244void 2245sc_clear_screen(scr_stat *scp) 2246{ 2247 move_crsr(scp, 0, 0); 2248 scp->cursor_oldpos = scp->cursor_pos; 2249 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2250 scp->xsize * scp->ysize); 2251 mark_all(scp); 2252 remove_cutmarking(scp); 2253} 2254 2255static int 2256switch_scr(scr_stat *scp, u_int next_scr) 2257{ 2258 /* delay switch if actively updating screen */ 2259 if (scrn_blanked > 0 || write_in_progress || blink_in_progress) { 2260 scsplash_stick(FALSE); 2261 run_scrn_saver = FALSE; 2262 delayed_next_scr = next_scr+1; 2263 return 0; 2264 } 2265 2266 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 2267 switch_in_progress = FALSE; 2268 2269 if (next_scr >= MAXCONS || switch_in_progress || 2270 (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { 2271 do_bell(scp, BELL_PITCH, BELL_DURATION); 2272 return EINVAL; 2273 } 2274 2275 /* is the wanted virtual console open ? */ 2276 if (next_scr) { 2277 struct tty *tp = VIRTUAL_TTY(next_scr); 2278 if (!(tp->t_state & TS_ISOPEN)) { 2279 do_bell(scp, BELL_PITCH, BELL_DURATION); 2280 return EINVAL; 2281 } 2282 } 2283 2284 switch_in_progress = TRUE; 2285 old_scp = cur_console; 2286 new_scp = console[next_scr]; 2287 wakeup((caddr_t)&new_scp->smode); 2288 if (new_scp == old_scp) { 2289 switch_in_progress = FALSE; 2290 delayed_next_scr = FALSE; 2291 return 0; 2292 } 2293 2294 /* has controlling process died? */ 2295 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 2296 old_scp->smode.mode = VT_AUTO; 2297 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 2298 new_scp->smode.mode = VT_AUTO; 2299 2300 /* check the modes and switch appropriately */ 2301 if (old_scp->smode.mode == VT_PROCESS) { 2302 old_scp->status |= SWITCH_WAIT_REL; 2303 psignal(old_scp->proc, old_scp->smode.relsig); 2304 } 2305 else { 2306 exchange_scr(); 2307 if (new_scp->smode.mode == VT_PROCESS) { 2308 new_scp->status |= SWITCH_WAIT_ACQ; 2309 psignal(new_scp->proc, new_scp->smode.acqsig); 2310 } 2311 else 2312 switch_in_progress = FALSE; 2313 } 2314 return 0; 2315} 2316 2317static void 2318exchange_scr(void) 2319{ 2320 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 2321 cur_console = new_scp; 2322 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) 2323 set_mode(new_scp); 2324 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 2325 if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) 2326 set_destructive_cursor(new_scp); 2327 if (ISGRAPHSC(old_scp)) 2328 load_palette(new_scp, palette); 2329 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || 2330 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) 2331 shfts = ctls = alts = agrs = metas = accents = 0; 2332 set_border(new_scp, new_scp->border); 2333 update_leds(new_scp->status); 2334 delayed_next_scr = FALSE; 2335 mark_all(new_scp); 2336} 2337 2338static void 2339scan_esc(scr_stat *scp, u_char c) 2340{ 2341 static u_char ansi_col[16] = 2342 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2343 int i, n; 2344 u_short *src, *dst, count; 2345 2346 if (scp->term.esc == 1) { /* seen ESC */ 2347 switch (c) { 2348 2349 case '7': /* Save cursor position */ 2350 scp->saved_xpos = scp->xpos; 2351 scp->saved_ypos = scp->ypos; 2352 break; 2353 2354 case '8': /* Restore saved cursor position */ 2355 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2356 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2357 break; 2358 2359 case '[': /* Start ESC [ sequence */ 2360 scp->term.esc = 2; 2361 scp->term.last_param = -1; 2362 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2363 scp->term.param[i] = 1; 2364 scp->term.num_param = 0; 2365 return; 2366 2367 case 'M': /* Move cursor up 1 line, scroll if at top */ 2368 if (scp->ypos > 0) 2369 move_crsr(scp, scp->xpos, scp->ypos - 1); 2370 else { 2371 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 2372 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 2373 fillw(scp->term.cur_color | scr_map[0x20], 2374 scp->scr_buf, scp->xsize); 2375 mark_all(scp); 2376 } 2377 break; 2378#if notyet 2379 case 'Q': 2380 scp->term.esc = 4; 2381 return; 2382#endif 2383 case 'c': /* Clear screen & home */ 2384 sc_clear_screen(scp); 2385 break; 2386 2387 case '(': /* iso-2022: designate 94 character set to G0 */ 2388 scp->term.esc = 5; 2389 return; 2390 } 2391 } 2392 else if (scp->term.esc == 2) { /* seen ESC [ */ 2393 if (c >= '0' && c <= '9') { 2394 if (scp->term.num_param < MAX_ESC_PAR) { 2395 if (scp->term.last_param != scp->term.num_param) { 2396 scp->term.last_param = scp->term.num_param; 2397 scp->term.param[scp->term.num_param] = 0; 2398 } 2399 else 2400 scp->term.param[scp->term.num_param] *= 10; 2401 scp->term.param[scp->term.num_param] += c - '0'; 2402 return; 2403 } 2404 } 2405 scp->term.num_param = scp->term.last_param + 1; 2406 switch (c) { 2407 2408 case ';': 2409 if (scp->term.num_param < MAX_ESC_PAR) 2410 return; 2411 break; 2412 2413 case '=': 2414 scp->term.esc = 3; 2415 scp->term.last_param = -1; 2416 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2417 scp->term.param[i] = 1; 2418 scp->term.num_param = 0; 2419 return; 2420 2421 case 'A': /* up n rows */ 2422 n = scp->term.param[0]; if (n < 1) n = 1; 2423 move_crsr(scp, scp->xpos, scp->ypos - n); 2424 break; 2425 2426 case 'B': /* down n rows */ 2427 n = scp->term.param[0]; if (n < 1) n = 1; 2428 move_crsr(scp, scp->xpos, scp->ypos + n); 2429 break; 2430 2431 case 'C': /* right n columns */ 2432 n = scp->term.param[0]; if (n < 1) n = 1; 2433 move_crsr(scp, scp->xpos + n, scp->ypos); 2434 break; 2435 2436 case 'D': /* left n columns */ 2437 n = scp->term.param[0]; if (n < 1) n = 1; 2438 move_crsr(scp, scp->xpos - n, scp->ypos); 2439 break; 2440 2441 case 'E': /* cursor to start of line n lines down */ 2442 n = scp->term.param[0]; if (n < 1) n = 1; 2443 move_crsr(scp, 0, scp->ypos + n); 2444 break; 2445 2446 case 'F': /* cursor to start of line n lines up */ 2447 n = scp->term.param[0]; if (n < 1) n = 1; 2448 move_crsr(scp, 0, scp->ypos - n); 2449 break; 2450 2451 case 'f': /* Cursor move */ 2452 case 'H': 2453 if (scp->term.num_param == 0) 2454 move_crsr(scp, 0, 0); 2455 else if (scp->term.num_param == 2) 2456 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2457 break; 2458 2459 case 'J': /* Clear all or part of display */ 2460 if (scp->term.num_param == 0) 2461 n = 0; 2462 else 2463 n = scp->term.param[0]; 2464 switch (n) { 2465 case 0: /* clear form cursor to end of display */ 2466 fillw(scp->term.cur_color | scr_map[0x20], 2467 scp->cursor_pos, 2468 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2469 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2470 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2471 remove_cutmarking(scp); 2472 break; 2473 case 1: /* clear from beginning of display to cursor */ 2474 fillw(scp->term.cur_color | scr_map[0x20], 2475 scp->scr_buf, 2476 scp->cursor_pos - scp->scr_buf); 2477 mark_for_update(scp, 0); 2478 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2479 remove_cutmarking(scp); 2480 break; 2481 case 2: /* clear entire display */ 2482 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2483 scp->xsize * scp->ysize); 2484 mark_all(scp); 2485 remove_cutmarking(scp); 2486 break; 2487 } 2488 break; 2489 2490 case 'K': /* Clear all or part of line */ 2491 if (scp->term.num_param == 0) 2492 n = 0; 2493 else 2494 n = scp->term.param[0]; 2495 switch (n) { 2496 case 0: /* clear form cursor to end of line */ 2497 fillw(scp->term.cur_color | scr_map[0x20], 2498 scp->cursor_pos, 2499 scp->xsize - scp->xpos); 2500 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2501 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2502 scp->xsize - 1 - scp->xpos); 2503 break; 2504 case 1: /* clear from beginning of line to cursor */ 2505 fillw(scp->term.cur_color | scr_map[0x20], 2506 scp->cursor_pos - scp->xpos, 2507 scp->xpos + 1); 2508 mark_for_update(scp, scp->ypos * scp->xsize); 2509 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2510 break; 2511 case 2: /* clear entire line */ 2512 fillw(scp->term.cur_color | scr_map[0x20], 2513 scp->cursor_pos - scp->xpos, 2514 scp->xsize); 2515 mark_for_update(scp, scp->ypos * scp->xsize); 2516 mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); 2517 break; 2518 } 2519 break; 2520 2521 case 'L': /* Insert n lines */ 2522 n = scp->term.param[0]; if (n < 1) n = 1; 2523 if (n > scp->ysize - scp->ypos) 2524 n = scp->ysize - scp->ypos; 2525 src = scp->scr_buf + scp->ypos * scp->xsize; 2526 dst = src + n * scp->xsize; 2527 count = scp->ysize - (scp->ypos + n); 2528 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2529 fillw(scp->term.cur_color | scr_map[0x20], src, 2530 n * scp->xsize); 2531 mark_for_update(scp, scp->ypos * scp->xsize); 2532 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2533 break; 2534 2535 case 'M': /* Delete 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 dst = scp->scr_buf + scp->ypos * scp->xsize; 2540 src = dst + n * scp->xsize; 2541 count = scp->ysize - (scp->ypos + n); 2542 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2543 src = dst + count * scp->xsize; 2544 fillw(scp->term.cur_color | scr_map[0x20], src, 2545 n * scp->xsize); 2546 mark_for_update(scp, scp->ypos * scp->xsize); 2547 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2548 break; 2549 2550 case 'P': /* Delete n chars */ 2551 n = scp->term.param[0]; if (n < 1) n = 1; 2552 if (n > scp->xsize - scp->xpos) 2553 n = scp->xsize - scp->xpos; 2554 dst = scp->cursor_pos; 2555 src = dst + n; 2556 count = scp->xsize - (scp->xpos + n); 2557 bcopy(src, dst, count * sizeof(u_short)); 2558 src = dst + count; 2559 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2560 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2561 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2562 break; 2563 2564 case '@': /* Insert 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 src = scp->cursor_pos; 2569 dst = src + n; 2570 count = scp->xsize - (scp->xpos + n); 2571 bcopy(src, dst, count * sizeof(u_short)); 2572 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2573 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2574 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2575 break; 2576 2577 case 'S': /* scroll up n lines */ 2578 n = scp->term.param[0]; if (n < 1) n = 1; 2579 if (n > scp->ysize) 2580 n = scp->ysize; 2581 bcopy(scp->scr_buf + (scp->xsize * n), 2582 scp->scr_buf, 2583 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2584 fillw(scp->term.cur_color | scr_map[0x20], 2585 scp->scr_buf + scp->xsize * (scp->ysize - n), 2586 scp->xsize * n); 2587 mark_all(scp); 2588 break; 2589 2590 case 'T': /* scroll down n lines */ 2591 n = scp->term.param[0]; if (n < 1) n = 1; 2592 if (n > scp->ysize) 2593 n = scp->ysize; 2594 bcopy(scp->scr_buf, 2595 scp->scr_buf + (scp->xsize * n), 2596 scp->xsize * (scp->ysize - n) * 2597 sizeof(u_short)); 2598 fillw(scp->term.cur_color | scr_map[0x20], 2599 scp->scr_buf, scp->xsize * n); 2600 mark_all(scp); 2601 break; 2602 2603 case 'X': /* erase n characters in line */ 2604 n = scp->term.param[0]; if (n < 1) n = 1; 2605 if (n > scp->xsize - scp->xpos) 2606 n = scp->xsize - scp->xpos; 2607 fillw(scp->term.cur_color | scr_map[0x20], 2608 scp->cursor_pos, n); 2609 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2610 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1); 2611 break; 2612 2613 case 'Z': /* move n tabs backwards */ 2614 n = scp->term.param[0]; if (n < 1) n = 1; 2615 if ((i = scp->xpos & 0xf8) == scp->xpos) 2616 i -= 8*n; 2617 else 2618 i -= 8*(n-1); 2619 if (i < 0) 2620 i = 0; 2621 move_crsr(scp, i, scp->ypos); 2622 break; 2623 2624 case '`': /* move cursor to column n */ 2625 n = scp->term.param[0]; if (n < 1) n = 1; 2626 move_crsr(scp, n - 1, scp->ypos); 2627 break; 2628 2629 case 'a': /* move cursor n columns to the right */ 2630 n = scp->term.param[0]; if (n < 1) n = 1; 2631 move_crsr(scp, scp->xpos + n, scp->ypos); 2632 break; 2633 2634 case 'd': /* move cursor to row n */ 2635 n = scp->term.param[0]; if (n < 1) n = 1; 2636 move_crsr(scp, scp->xpos, n - 1); 2637 break; 2638 2639 case 'e': /* move cursor n rows down */ 2640 n = scp->term.param[0]; if (n < 1) n = 1; 2641 move_crsr(scp, scp->xpos, scp->ypos + n); 2642 break; 2643 2644 case 'm': /* change attribute */ 2645 if (scp->term.num_param == 0) { 2646 scp->term.attr_mask = NORMAL_ATTR; 2647 scp->term.cur_attr = 2648 scp->term.cur_color = scp->term.std_color; 2649 break; 2650 } 2651 for (i = 0; i < scp->term.num_param; i++) { 2652 switch (n = scp->term.param[i]) { 2653 case 0: /* back to normal */ 2654 scp->term.attr_mask = NORMAL_ATTR; 2655 scp->term.cur_attr = 2656 scp->term.cur_color = scp->term.std_color; 2657 break; 2658 case 1: /* bold */ 2659 scp->term.attr_mask |= BOLD_ATTR; 2660 scp->term.cur_attr = mask2attr(&scp->term); 2661 break; 2662 case 4: /* underline */ 2663 scp->term.attr_mask |= UNDERLINE_ATTR; 2664 scp->term.cur_attr = mask2attr(&scp->term); 2665 break; 2666 case 5: /* blink */ 2667 scp->term.attr_mask |= BLINK_ATTR; 2668 scp->term.cur_attr = mask2attr(&scp->term); 2669 break; 2670 case 7: /* reverse video */ 2671 scp->term.attr_mask |= REVERSE_ATTR; 2672 scp->term.cur_attr = mask2attr(&scp->term); 2673 break; 2674 case 30: case 31: /* set fg color */ 2675 case 32: case 33: case 34: 2676 case 35: case 36: case 37: 2677 scp->term.attr_mask |= FOREGROUND_CHANGED; 2678 scp->term.cur_color = 2679 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2680 scp->term.cur_attr = mask2attr(&scp->term); 2681 break; 2682 case 40: case 41: /* set bg color */ 2683 case 42: case 43: case 44: 2684 case 45: case 46: case 47: 2685 scp->term.attr_mask |= BACKGROUND_CHANGED; 2686 scp->term.cur_color = 2687 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2688 scp->term.cur_attr = mask2attr(&scp->term); 2689 break; 2690 } 2691 } 2692 break; 2693 2694 case 's': /* Save cursor position */ 2695 scp->saved_xpos = scp->xpos; 2696 scp->saved_ypos = scp->ypos; 2697 break; 2698 2699 case 'u': /* Restore saved cursor position */ 2700 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2701 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2702 break; 2703 2704 case 'x': 2705 if (scp->term.num_param == 0) 2706 n = 0; 2707 else 2708 n = scp->term.param[0]; 2709 switch (n) { 2710 case 0: /* reset attributes */ 2711 scp->term.attr_mask = NORMAL_ATTR; 2712 scp->term.cur_attr = 2713 scp->term.cur_color = scp->term.std_color = 2714 current_default->std_color; 2715 scp->term.rev_color = current_default->rev_color; 2716 break; 2717 case 1: /* set ansi background */ 2718 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2719 scp->term.cur_color = scp->term.std_color = 2720 (scp->term.std_color & 0x0F00) | 2721 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2722 scp->term.cur_attr = mask2attr(&scp->term); 2723 break; 2724 case 2: /* set ansi foreground */ 2725 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2726 scp->term.cur_color = scp->term.std_color = 2727 (scp->term.std_color & 0xF000) | 2728 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2729 scp->term.cur_attr = mask2attr(&scp->term); 2730 break; 2731 case 3: /* set ansi attribute directly */ 2732 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2733 scp->term.cur_color = scp->term.std_color = 2734 (scp->term.param[1]&0xFF)<<8; 2735 scp->term.cur_attr = mask2attr(&scp->term); 2736 break; 2737 case 5: /* set ansi reverse video background */ 2738 scp->term.rev_color = 2739 (scp->term.rev_color & 0x0F00) | 2740 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2741 scp->term.cur_attr = mask2attr(&scp->term); 2742 break; 2743 case 6: /* set ansi reverse video foreground */ 2744 scp->term.rev_color = 2745 (scp->term.rev_color & 0xF000) | 2746 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2747 scp->term.cur_attr = mask2attr(&scp->term); 2748 break; 2749 case 7: /* set ansi reverse video directly */ 2750 scp->term.rev_color = 2751 (scp->term.param[1]&0xFF)<<8; 2752 scp->term.cur_attr = mask2attr(&scp->term); 2753 break; 2754 } 2755 break; 2756 2757 case 'z': /* switch to (virtual) console n */ 2758 if (scp->term.num_param == 1) 2759 switch_scr(scp, scp->term.param[0]); 2760 break; 2761 } 2762 } 2763 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2764 if (c >= '0' && c <= '9') { 2765 if (scp->term.num_param < MAX_ESC_PAR) { 2766 if (scp->term.last_param != scp->term.num_param) { 2767 scp->term.last_param = scp->term.num_param; 2768 scp->term.param[scp->term.num_param] = 0; 2769 } 2770 else 2771 scp->term.param[scp->term.num_param] *= 10; 2772 scp->term.param[scp->term.num_param] += c - '0'; 2773 return; 2774 } 2775 } 2776 scp->term.num_param = scp->term.last_param + 1; 2777 switch (c) { 2778 2779 case ';': 2780 if (scp->term.num_param < MAX_ESC_PAR) 2781 return; 2782 break; 2783 2784 case 'A': /* set display border color */ 2785 if (scp->term.num_param == 1) { 2786 scp->border=scp->term.param[0] & 0xff; 2787 if (scp == cur_console) 2788 set_border(cur_console, scp->border); 2789 } 2790 break; 2791 2792 case 'B': /* set bell pitch and duration */ 2793 if (scp->term.num_param == 2) { 2794 scp->bell_pitch = scp->term.param[0]; 2795 scp->bell_duration = scp->term.param[1]; 2796 } 2797 break; 2798 2799 case 'C': /* set cursor type & shape */ 2800 if (scp->term.num_param == 1) { 2801 if (scp->term.param[0] & 0x01) 2802 sc_flags |= BLINK_CURSOR; 2803 else 2804 sc_flags &= ~BLINK_CURSOR; 2805 if ((scp->term.param[0] & 0x02) 2806 && ISFONTAVAIL(get_adapter(scp)->va_flags)) 2807 sc_flags |= CHAR_CURSOR; 2808 else 2809 sc_flags &= ~CHAR_CURSOR; 2810 } 2811 else if (scp->term.num_param == 2) { 2812 scp->cursor_start = scp->term.param[0] & 0x1F; 2813 scp->cursor_end = scp->term.param[1] & 0x1F; 2814 } 2815 /* 2816 * The cursor shape is global property; all virtual consoles 2817 * are affected. Update the cursor in the current console... 2818 */ 2819 if (!ISGRAPHSC(cur_console)) { 2820 remove_cursor_image(cur_console); 2821 if (sc_flags & CHAR_CURSOR) 2822 set_destructive_cursor(cur_console); 2823 draw_cursor_image(cur_console); 2824 } 2825 break; 2826 2827 case 'F': /* set ansi foreground */ 2828 if (scp->term.num_param == 1) { 2829 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2830 scp->term.cur_color = scp->term.std_color = 2831 (scp->term.std_color & 0xF000) 2832 | ((scp->term.param[0] & 0x0F) << 8); 2833 scp->term.cur_attr = mask2attr(&scp->term); 2834 } 2835 break; 2836 2837 case 'G': /* set ansi background */ 2838 if (scp->term.num_param == 1) { 2839 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2840 scp->term.cur_color = scp->term.std_color = 2841 (scp->term.std_color & 0x0F00) 2842 | ((scp->term.param[0] & 0x0F) << 12); 2843 scp->term.cur_attr = mask2attr(&scp->term); 2844 } 2845 break; 2846 2847 case 'H': /* set ansi reverse video foreground */ 2848 if (scp->term.num_param == 1) { 2849 scp->term.rev_color = 2850 (scp->term.rev_color & 0xF000) 2851 | ((scp->term.param[0] & 0x0F) << 8); 2852 scp->term.cur_attr = mask2attr(&scp->term); 2853 } 2854 break; 2855 2856 case 'I': /* set ansi reverse video background */ 2857 if (scp->term.num_param == 1) { 2858 scp->term.rev_color = 2859 (scp->term.rev_color & 0x0F00) 2860 | ((scp->term.param[0] & 0x0F) << 12); 2861 scp->term.cur_attr = mask2attr(&scp->term); 2862 } 2863 break; 2864 } 2865 } 2866#if notyet 2867 else if (scp->term.esc == 4) { /* seen ESC Q */ 2868 /* to be filled */ 2869 } 2870#endif 2871 else if (scp->term.esc == 5) { /* seen ESC ( */ 2872 switch (c) { 2873 case 'B': /* iso-2022: desginate ASCII into G0 */ 2874 break; 2875 /* other items to be filled */ 2876 default: 2877 break; 2878 } 2879 } 2880 scp->term.esc = 0; 2881} 2882 2883static void 2884ansi_put(scr_stat *scp, u_char *buf, int len) 2885{ 2886 u_char *ptr = buf; 2887 2888 /* make screensaver happy */ 2889 if (!sticky_splash && scp == cur_console) 2890 run_scrn_saver = FALSE; 2891 2892 write_in_progress++; 2893outloop: 2894 if (scp->term.esc) { 2895 scan_esc(scp, *ptr++); 2896 len--; 2897 } 2898 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2899 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2900 u_short cur_attr = scp->term.cur_attr; 2901 u_short *cursor_pos = scp->cursor_pos; 2902 do { 2903 /* 2904 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2905 * pointers in the following to volatile should have no effect, 2906 * but in fact speeds up this inner loop from 26 to 18 cycles 2907 * (+ cache misses) on i486's. 2908 */ 2909#define UCVP(ucp) ((u_char volatile *)(ucp)) 2910 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2911 ptr++; 2912 cnt--; 2913 } while (cnt && PRINTABLE(*ptr)); 2914 len -= (cursor_pos - scp->cursor_pos); 2915 scp->xpos += (cursor_pos - scp->cursor_pos); 2916 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2917 mark_for_update(scp, cursor_pos - scp->scr_buf); 2918 scp->cursor_pos = cursor_pos; 2919 if (scp->xpos >= scp->xsize) { 2920 scp->xpos = 0; 2921 scp->ypos++; 2922 } 2923 } 2924 else { 2925 switch(*ptr) { 2926 case 0x07: 2927 do_bell(scp, scp->bell_pitch, scp->bell_duration); 2928 break; 2929 2930 case 0x08: /* non-destructive backspace */ 2931 if (scp->cursor_pos > scp->scr_buf) { 2932 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2933 scp->cursor_pos--; 2934 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2935 if (scp->xpos > 0) 2936 scp->xpos--; 2937 else { 2938 scp->xpos += scp->xsize - 1; 2939 scp->ypos--; 2940 } 2941 } 2942 break; 2943 2944 case 0x09: /* non-destructive tab */ 2945 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2946 scp->cursor_pos += (8 - scp->xpos % 8u); 2947 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2948 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 2949 scp->xpos = 0; 2950 scp->ypos++; 2951 } 2952 break; 2953 2954 case 0x0a: /* newline, same pos */ 2955 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2956 scp->cursor_pos += scp->xsize; 2957 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2958 scp->ypos++; 2959 break; 2960 2961 case 0x0c: /* form feed, clears screen */ 2962 sc_clear_screen(scp); 2963 break; 2964 2965 case 0x0d: /* return, return to pos 0 */ 2966 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2967 scp->cursor_pos -= scp->xpos; 2968 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2969 scp->xpos = 0; 2970 break; 2971 2972 case 0x1b: /* start escape sequence */ 2973 scp->term.esc = 1; 2974 scp->term.num_param = 0; 2975 break; 2976 } 2977 ptr++; len--; 2978 } 2979 /* do we have to scroll ?? */ 2980 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 2981 remove_cutmarking(scp); 2982 if (scp->history != NULL) { 2983 bcopy(scp->scr_buf, scp->history_head, 2984 scp->xsize * sizeof(u_short)); 2985 scp->history_head += scp->xsize; 2986 if (scp->history_head + scp->xsize > 2987 scp->history + scp->history_size) 2988 scp->history_head = scp->history; 2989 } 2990 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 2991 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2992 fillw(scp->term.cur_color | scr_map[0x20], 2993 scp->scr_buf + scp->xsize * (scp->ysize - 1), 2994 scp->xsize); 2995 scp->cursor_pos -= scp->xsize; 2996 scp->ypos--; 2997 mark_all(scp); 2998 } 2999 if (len) 3000 goto outloop; 3001 write_in_progress--; 3002 if (delayed_next_scr) 3003 switch_scr(scp, delayed_next_scr - 1); 3004} 3005 3006static void 3007scinit(void) 3008{ 3009 int col; 3010 int row; 3011 u_int i; 3012 3013 if (init_done != COLD) 3014 return; 3015 init_done = WARM; 3016 3017 /* extract the hardware cursor location and move it out of the way */ 3018 (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row); 3019 (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1); 3020 3021 /* set up the first console */ 3022 current_default = &user_default; 3023 console[0] = &main_console; 3024 init_scp(console[0]); 3025 cur_console = console[0]; 3026 3027 /* copy screen to temporary buffer */ 3028 if (ISTEXTSC(console[0])) 3029 generic_bcopy((ushort *)(get_adapter(console[0])->va_window), sc_buffer, 3030 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 3031 3032 console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos 3033 = sc_buffer; 3034 if (col >= console[0]->xsize) 3035 col = 0; 3036 if (row >= console[0]->ysize) 3037 row = console[0]->ysize - 1; 3038 console[0]->xpos = col; 3039 console[0]->ypos = row; 3040 console[0]->cursor_pos = console[0]->cursor_oldpos = 3041 sc_buffer + row*console[0]->xsize + col; 3042 console[0]->cursor_saveunder = *console[0]->cursor_pos; 3043 for (i=1; i<MAXCONS; i++) 3044 console[i] = NULL; 3045 kernel_console.esc = 0; 3046 kernel_console.attr_mask = NORMAL_ATTR; 3047 kernel_console.cur_attr = 3048 kernel_console.cur_color = kernel_console.std_color = 3049 kernel_default.std_color; 3050 kernel_console.rev_color = kernel_default.rev_color; 3051 3052 /* initialize mapscrn arrays to a one to one map */ 3053 for (i=0; i<sizeof(scr_map); i++) { 3054 scr_map[i] = scr_rmap[i] = i; 3055 } 3056 3057 /* Save font and palette */ 3058 if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) { 3059 if (fonts_loaded & FONT_16) { 3060 copy_font(cur_console, LOAD, 16, font_16); 3061 } else { 3062 copy_font(cur_console, SAVE, 16, font_16); 3063 fonts_loaded = FONT_16; 3064 set_destructive_cursor(cur_console); 3065 } 3066 /* 3067 * FONT KLUDGE 3068 * Always use the font page #0. XXX 3069 */ 3070 (*biosvidsw.show_font)(cur_console->adp, 0); 3071 } 3072 save_palette(cur_console, palette); 3073 3074#ifdef SC_SPLASH_SCREEN 3075 /* put up the splash. */ 3076 scsplash_init(cur_console); 3077#endif 3078} 3079 3080static void 3081scshutdown(int howto, void *arg) 3082{ 3083 scsplash_stick(FALSE); 3084 run_scrn_saver = FALSE; 3085 if (!cold && cur_console->smode.mode == VT_AUTO 3086 && console[0]->smode.mode == VT_AUTO) 3087 switch_scr(cur_console, 0); 3088 shutdown_in_progress = TRUE; 3089} 3090 3091int 3092sc_clean_up(scr_stat *scp) 3093{ 3094 int error; 3095 3096 if ((error = wait_scrn_saver_stop())) 3097 return error; 3098 scp->status &= ~MOUSE_VISIBLE; 3099 remove_cutmarking(scp); 3100 return 0; 3101} 3102 3103void 3104sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) 3105{ 3106 if (scp->scr_buf) 3107 free(scp->scr_buf, M_DEVBUF); 3108 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 3109 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3110 3111 if (clear) { 3112 /* clear the screen and move the text cursor to the top-left position */ 3113 sc_clear_screen(scp); 3114 } else { 3115 /* retain the current cursor position, but adjust pointers */ 3116 move_crsr(scp, scp->xpos, scp->ypos); 3117 scp->cursor_oldpos = scp->cursor_pos; 3118 } 3119 3120 /* move the mouse cursor at the center of the screen */ 3121 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); 3122} 3123 3124void 3125sc_alloc_cut_buffer(scr_stat *scp, int wait) 3126{ 3127 if ((cut_buffer == NULL) 3128 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 3129 if (cut_buffer != NULL) 3130 free(cut_buffer, M_DEVBUF); 3131 cut_buffer_size = scp->xsize * scp->ysize + 1; 3132 cut_buffer = (u_char *)malloc(cut_buffer_size, 3133 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3134 if (cut_buffer != NULL) 3135 cut_buffer[0] = '\0'; 3136 } 3137} 3138 3139void 3140sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) 3141{ 3142 u_short *usp; 3143 3144 if (lines < scp->ysize) 3145 lines = scp->ysize; 3146 3147 usp = scp->history; 3148 scp->history = NULL; 3149 if (usp != NULL) { 3150 free(usp, M_DEVBUF); 3151 if (extra > 0) 3152 extra_history_size += extra; 3153 } 3154 3155 scp->history_size = lines * scp->xsize; 3156 if (lines > imax(sc_history_size, scp->ysize)) 3157 extra_history_size -= lines - imax(sc_history_size, scp->ysize); 3158 usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 3159 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3160 if (usp != NULL) 3161 bzero(usp, scp->history_size * sizeof(u_short)); 3162 scp->history_head = scp->history_pos = usp; 3163 scp->history = usp; 3164} 3165 3166static scr_stat 3167*alloc_scp() 3168{ 3169 scr_stat *scp; 3170 3171 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3172 init_scp(scp); 3173 sc_alloc_scr_buffer(scp, TRUE, TRUE); 3174 if (ISMOUSEAVAIL(get_adapter(scp)->va_flags)) 3175 sc_alloc_cut_buffer(scp, TRUE); 3176 sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); 3177/* SOS 3178 if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE) 3179 set_mode(scp); 3180*/ 3181 sc_clear_screen(scp); 3182 scp->cursor_saveunder = *scp->cursor_pos; 3183 return scp; 3184} 3185 3186static void 3187init_scp(scr_stat *scp) 3188{ 3189 video_info_t info; 3190 3191 scp->adp = V_ADP_PRIMARY; 3192 (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info); 3193 3194 scp->status = 0; 3195 scp->mode = scp->initial_mode = initial_video_mode; 3196 scp->scr_buf = NULL; 3197 if (info.vi_flags & V_INFO_GRAPHICS) { 3198 scp->status |= GRAPHICS_MODE; 3199 scp->xpixel = info.vi_width; 3200 scp->ypixel = info.vi_height; 3201 scp->xsize = info.vi_width/8; 3202 scp->ysize = info.vi_height/info.vi_cheight; 3203 scp->font_size = FONT_NONE; 3204 } else { 3205 scp->xsize = info.vi_width; 3206 scp->ysize = info.vi_height; 3207 scp->xpixel = scp->xsize*8; 3208 scp->ypixel = scp->ysize*info.vi_cheight; 3209 scp->font_size = info.vi_cheight; 3210 } 3211 scp->xoff = scp->yoff = 0; 3212 scp->xpos = scp->ypos = 0; 3213 scp->saved_xpos = scp->saved_ypos = -1; 3214 scp->start = scp->xsize * scp->ysize; 3215 scp->end = 0; 3216 scp->term.esc = 0; 3217 scp->term.attr_mask = NORMAL_ATTR; 3218 scp->term.cur_attr = 3219 scp->term.cur_color = scp->term.std_color = 3220 current_default->std_color; 3221 scp->term.rev_color = current_default->rev_color; 3222 scp->border = BG_BLACK; 3223 scp->cursor_start = *(u_int8_t *)pa_to_va(0x461); 3224 scp->cursor_end = *(u_int8_t *)pa_to_va(0x460); 3225 scp->mouse_xpos = scp->xsize*8/2; 3226 scp->mouse_ypos = scp->ysize*scp->font_size/2; 3227 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3228 scp->mouse_signal = 0; 3229 scp->mouse_pid = 0; 3230 scp->mouse_proc = NULL; 3231 scp->bell_pitch = BELL_PITCH; 3232 scp->bell_duration = BELL_DURATION; 3233 scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 3234 scp->status |= CURSOR_ENABLED; 3235 scp->pid = 0; 3236 scp->proc = NULL; 3237 scp->smode.mode = VT_AUTO; 3238 scp->history_head = scp->history_pos = scp->history = NULL; 3239 scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; 3240} 3241 3242static u_char 3243*get_fstr(u_int c, u_int *len) 3244{ 3245 u_int i; 3246 3247 if (!(c & FKEY)) 3248 return(NULL); 3249 i = (c & 0xFF) - F_FN; 3250 if (i > n_fkey_tab) 3251 return(NULL); 3252 *len = fkey_tab[i].len; 3253 return(fkey_tab[i].str); 3254} 3255 3256static void 3257history_to_screen(scr_stat *scp) 3258{ 3259 int i; 3260 3261 for (i=0; i<scp->ysize; i++) 3262 bcopy(scp->history + (((scp->history_pos - scp->history) + 3263 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 3264 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 3265 scp->xsize * sizeof(u_short)); 3266 mark_all(scp); 3267} 3268 3269static int 3270history_up_line(scr_stat *scp) 3271{ 3272 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 3273 scp->history_head) { 3274 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 3275 history_to_screen(scp); 3276 return 0; 3277 } 3278 else 3279 return -1; 3280} 3281 3282static int 3283history_down_line(scr_stat *scp) 3284{ 3285 if (scp->history_pos != scp->history_head) { 3286 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 3287 history_to_screen(scp); 3288 return 0; 3289 } 3290 else 3291 return -1; 3292} 3293 3294/* 3295 * scgetc(flags) - get character from keyboard. 3296 * If flags & SCGETC_CN, then avoid harmful side effects. 3297 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3298 * return NOKEY if there is nothing there. 3299 */ 3300static u_int 3301scgetc(u_int flags) 3302{ 3303 struct key_t *key; 3304 u_char scancode, keycode; 3305 u_int state, action; 3306 int c; 3307 static u_char esc_flag = 0, compose = 0; 3308 static u_int chr = 0; 3309 3310next_code: 3311 /* first see if there is something in the keyboard port */ 3312 if (flags & SCGETC_NONBLOCK) { 3313 c = read_kbd_data_no_wait(sc_kbdc); 3314 if (c == -1) 3315 return(NOKEY); 3316 } else { 3317 do { 3318 c = read_kbd_data(sc_kbdc); 3319 } while(c == -1); 3320 } 3321 scancode = (u_char)c; 3322 3323 /* make screensaver happy */ 3324 if (!(scancode & 0x80)) { 3325 scsplash_stick(FALSE); 3326 run_scrn_saver = FALSE; 3327 } 3328 3329 if (!(flags & SCGETC_CN)) { 3330 /* do the /dev/random device a favour */ 3331 add_keyboard_randomness(scancode); 3332 3333 if (cur_console->status & KBD_RAW_MODE) 3334 return scancode; 3335 } 3336 3337 keycode = scancode & 0x7F; 3338 switch (esc_flag) { 3339 case 0x00: /* normal scancode */ 3340 switch(scancode) { 3341 case 0xB8: /* left alt (compose key) */ 3342 if (compose) { 3343 compose = 0; 3344 if (chr > 255) { 3345 do_bell(cur_console, 3346 BELL_PITCH, BELL_DURATION); 3347 chr = 0; 3348 } 3349 } 3350 break; 3351 case 0x38: 3352 if (!compose) { 3353 compose = 1; 3354 chr = 0; 3355 } 3356 break; 3357 case 0xE0: 3358 case 0xE1: 3359 esc_flag = scancode; 3360 goto next_code; 3361 } 3362 break; 3363 case 0xE0: /* 0xE0 prefix */ 3364 esc_flag = 0; 3365 switch (keycode) { 3366 case 0x1C: /* right enter key */ 3367 keycode = 0x59; 3368 break; 3369 case 0x1D: /* right ctrl key */ 3370 keycode = 0x5A; 3371 break; 3372 case 0x35: /* keypad divide key */ 3373 keycode = 0x5B; 3374 break; 3375 case 0x37: /* print scrn key */ 3376 keycode = 0x5C; 3377 break; 3378 case 0x38: /* right alt key (alt gr) */ 3379 keycode = 0x5D; 3380 break; 3381 case 0x47: /* grey home key */ 3382 keycode = 0x5E; 3383 break; 3384 case 0x48: /* grey up arrow key */ 3385 keycode = 0x5F; 3386 break; 3387 case 0x49: /* grey page up key */ 3388 keycode = 0x60; 3389 break; 3390 case 0x4B: /* grey left arrow key */ 3391 keycode = 0x61; 3392 break; 3393 case 0x4D: /* grey right arrow key */ 3394 keycode = 0x62; 3395 break; 3396 case 0x4F: /* grey end key */ 3397 keycode = 0x63; 3398 break; 3399 case 0x50: /* grey down arrow key */ 3400 keycode = 0x64; 3401 break; 3402 case 0x51: /* grey page down key */ 3403 keycode = 0x65; 3404 break; 3405 case 0x52: /* grey insert key */ 3406 keycode = 0x66; 3407 break; 3408 case 0x53: /* grey delete key */ 3409 keycode = 0x67; 3410 break; 3411 3412 /* the following 3 are only used on the MS "Natural" keyboard */ 3413 case 0x5b: /* left Window key */ 3414 keycode = 0x69; 3415 break; 3416 case 0x5c: /* right Window key */ 3417 keycode = 0x6a; 3418 break; 3419 case 0x5d: /* menu key */ 3420 keycode = 0x6b; 3421 break; 3422 default: /* ignore everything else */ 3423 goto next_code; 3424 } 3425 break; 3426 case 0xE1: /* 0xE1 prefix */ 3427 esc_flag = 0; 3428 if (keycode == 0x1D) 3429 esc_flag = 0x1D; 3430 goto next_code; 3431 /* NOT REACHED */ 3432 case 0x1D: /* pause / break */ 3433 esc_flag = 0; 3434 if (keycode != 0x45) 3435 goto next_code; 3436 keycode = 0x68; 3437 break; 3438 } 3439 3440 if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE)) 3441 return (keycode | (scancode & 0x80)); 3442 3443 /* if scroll-lock pressed allow history browsing */ 3444 if (cur_console->history && cur_console->status & SLKED) { 3445 int i; 3446 3447 cur_console->status &= ~CURSOR_ENABLED; 3448 if (!(cur_console->status & BUFFER_SAVED)) { 3449 cur_console->status |= BUFFER_SAVED; 3450 cur_console->history_save = cur_console->history_head; 3451 3452 /* copy screen into top of history buffer */ 3453 for (i=0; i<cur_console->ysize; i++) { 3454 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 3455 cur_console->history_head, 3456 cur_console->xsize * sizeof(u_short)); 3457 cur_console->history_head += cur_console->xsize; 3458 if (cur_console->history_head + cur_console->xsize > 3459 cur_console->history + cur_console->history_size) 3460 cur_console->history_head=cur_console->history; 3461 } 3462 cur_console->history_pos = cur_console->history_head; 3463 history_to_screen(cur_console); 3464 } 3465 switch (scancode) { 3466 case 0x47: /* home key */ 3467 cur_console->history_pos = cur_console->history_head; 3468 history_to_screen(cur_console); 3469 goto next_code; 3470 3471 case 0x4F: /* end key */ 3472 cur_console->history_pos = 3473 WRAPHIST(cur_console, cur_console->history_head, 3474 cur_console->xsize*cur_console->ysize); 3475 history_to_screen(cur_console); 3476 goto next_code; 3477 3478 case 0x48: /* up arrow key */ 3479 if (history_up_line(cur_console)) 3480 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3481 goto next_code; 3482 3483 case 0x50: /* down arrow key */ 3484 if (history_down_line(cur_console)) 3485 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3486 goto next_code; 3487 3488 case 0x49: /* page up key */ 3489 for (i=0; i<cur_console->ysize; i++) 3490 if (history_up_line(cur_console)) { 3491 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3492 break; 3493 } 3494 goto next_code; 3495 3496 case 0x51: /* page down key */ 3497 for (i=0; i<cur_console->ysize; i++) 3498 if (history_down_line(cur_console)) { 3499 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3500 break; 3501 } 3502 goto next_code; 3503 } 3504 } 3505 3506 if (compose) { 3507 switch (scancode) { 3508 /* key pressed process it */ 3509 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 3510 chr = (scancode - 0x40) + chr*10; 3511 goto next_code; 3512 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 3513 chr = (scancode - 0x47) + chr*10; 3514 goto next_code; 3515 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 3516 chr = (scancode - 0x4E) + chr*10; 3517 goto next_code; 3518 case 0x52: /* keypad 0 */ 3519 chr *= 10; 3520 goto next_code; 3521 3522 /* key release, no interest here */ 3523 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 3524 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 3525 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 3526 case 0xD2: /* keypad 0 */ 3527 goto next_code; 3528 3529 case 0x38: /* left alt key */ 3530 break; 3531 default: 3532 if (chr) { 3533 compose = chr = 0; 3534 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3535 goto next_code; 3536 } 3537 break; 3538 } 3539 } 3540 3541 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 3542 if ((!agrs && (cur_console->status & ALKED)) 3543 || (agrs && !(cur_console->status & ALKED))) 3544 keycode += ALTGR_OFFSET; 3545 key = &key_map.key[keycode]; 3546 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 3547 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 3548 state ^= 1; 3549 3550 /* Check for make/break */ 3551 action = key->map[state]; 3552 if (scancode & 0x80) { /* key released */ 3553 if (key->spcl & (0x80>>state)) { 3554 switch (action) { 3555 case LSH: 3556 shfts &= ~1; 3557 break; 3558 case RSH: 3559 shfts &= ~2; 3560 break; 3561 case LCTR: 3562 ctls &= ~1; 3563 break; 3564 case RCTR: 3565 ctls &= ~2; 3566 break; 3567 case LALT: 3568 alts &= ~1; 3569 break; 3570 case RALT: 3571 alts &= ~2; 3572 break; 3573 case NLK: 3574 nlkcnt = 0; 3575 break; 3576 case CLK: 3577 clkcnt = 0; 3578 break; 3579 case SLK: 3580 slkcnt = 0; 3581 break; 3582 case ASH: 3583 agrs = 0; 3584 break; 3585 case ALK: 3586 alkcnt = 0; 3587 break; 3588 case META: 3589 metas = 0; 3590 break; 3591 } 3592 } 3593 if (chr && !compose) { 3594 action = chr; 3595 chr = 0; 3596 return(action); 3597 } 3598 } else { 3599 /* key pressed */ 3600 if (key->spcl & (0x80>>state)) { 3601 switch (action) { 3602 /* LOCKING KEYS */ 3603 case NLK: 3604 if (!nlkcnt) { 3605 nlkcnt++; 3606 if (cur_console->status & NLKED) 3607 cur_console->status &= ~NLKED; 3608 else 3609 cur_console->status |= NLKED; 3610 update_leds(cur_console->status); 3611 } 3612 break; 3613 case CLK: 3614 if (!clkcnt) { 3615 clkcnt++; 3616 if (cur_console->status & CLKED) 3617 cur_console->status &= ~CLKED; 3618 else 3619 cur_console->status |= CLKED; 3620 update_leds(cur_console->status); 3621 } 3622 break; 3623 case SLK: 3624 if (!slkcnt) { 3625 slkcnt++; 3626 if (cur_console->status & SLKED) { 3627 cur_console->status &= ~SLKED; 3628 if (cur_console->status & BUFFER_SAVED){ 3629 int i; 3630 u_short *ptr = cur_console->history_save; 3631 3632 for (i=0; i<cur_console->ysize; i++) { 3633 bcopy(ptr, 3634 cur_console->scr_buf + 3635 (cur_console->xsize*i), 3636 cur_console->xsize * sizeof(u_short)); 3637 ptr += cur_console->xsize; 3638 if (ptr + cur_console->xsize > 3639 cur_console->history + 3640 cur_console->history_size) 3641 ptr = cur_console->history; 3642 } 3643 cur_console->status &= ~BUFFER_SAVED; 3644 cur_console->history_head=cur_console->history_save; 3645 cur_console->status |= CURSOR_ENABLED; 3646 mark_all(cur_console); 3647 } 3648 scstart(VIRTUAL_TTY(get_scr_num())); 3649 } 3650 else 3651 cur_console->status |= SLKED; 3652 update_leds(cur_console->status); 3653 } 3654 break; 3655 case ALK: 3656 if (!alkcnt) { 3657 alkcnt++; 3658 if (cur_console->status & ALKED) 3659 cur_console->status &= ~ALKED; 3660 else 3661 cur_console->status |= ALKED; 3662 update_leds(cur_console->status); 3663 } 3664 break; 3665 3666 /* NON-LOCKING KEYS */ 3667 case NOP: 3668 break; 3669 case SPSC: 3670 /* force activatation/deactivation of the screen saver */ 3671 accents = 0; 3672 if (scrn_blanked <= 0) { 3673 run_scrn_saver = TRUE; 3674 scrn_time_stamp -= scrn_blank_time; 3675 } 3676#ifdef SC_SPLASH_SCREEN 3677 if (cold) { 3678 /* 3679 * While devices are being probed, the screen saver need 3680 * to be invoked explictly. XXX 3681 */ 3682 if (scrn_blanked > 0) { 3683 scsplash_stick(FALSE); 3684 stop_scrn_saver(current_saver); 3685 } else { 3686 if (!ISGRAPHSC(cur_console)) { 3687 scsplash_stick(TRUE); 3688 scrn_saver(current_saver, TRUE); 3689 } 3690 } 3691 } 3692#endif 3693 break; 3694 case RBT: 3695#ifndef SC_DISABLE_REBOOT 3696 accents = 0; 3697 shutdown_nice(); 3698#endif 3699 break; 3700 case SUSP: 3701#if NAPM > 0 3702 accents = 0; 3703 apm_suspend(PMST_SUSPEND); 3704#endif 3705 break; 3706 3707 case STBY: 3708#if NAPM > 0 3709 accents = 0; 3710 apm_suspend(PMST_STANDBY); 3711#endif 3712 break; 3713 3714 case DBG: 3715#ifdef DDB /* try to switch to console 0 */ 3716 accents = 0; 3717 /* 3718 * TRY to make sure the screen saver is stopped, 3719 * and the screen is updated before switching to 3720 * the vty0. 3721 */ 3722 scrn_timer((void *)FALSE); 3723 if (cur_console->smode.mode == VT_AUTO && 3724 console[0]->smode.mode == VT_AUTO) 3725 switch_scr(cur_console, 0); 3726 Debugger("manual escape to debugger"); 3727#else 3728 printf("No debugger in kernel\n"); 3729#endif 3730 break; 3731 case LSH: 3732 shfts |= 1; 3733 break; 3734 case RSH: 3735 shfts |= 2; 3736 break; 3737 case LCTR: 3738 ctls |= 1; 3739 break; 3740 case RCTR: 3741 ctls |= 2; 3742 break; 3743 case LALT: 3744 alts |= 1; 3745 break; 3746 case RALT: 3747 alts |= 2; 3748 break; 3749 case ASH: 3750 agrs = 1; 3751 break; 3752 case META: 3753 metas = 1; 3754 break; 3755 case NEXT: 3756 { 3757 int next, this = get_scr_num(); 3758 accents = 0; 3759 for (next = this+1; next != this; next = (next+1)%MAXCONS) { 3760 struct tty *tp = VIRTUAL_TTY(next); 3761 if (tp->t_state & TS_ISOPEN) { 3762 switch_scr(cur_console, next); 3763 break; 3764 } 3765 } 3766 } 3767 break; 3768 case BTAB: 3769 accents = 0; 3770 return(BKEY); 3771 default: 3772 if (action >= F_ACC && action <= L_ACC) { 3773 /* turn it into an index */ 3774 action -= F_ACC - 1; 3775 if ((action > accent_map.n_accs) 3776 || (accent_map.acc[action - 1].accchar == 0)) { 3777 /* 3778 * The index is out of range or pointing to an 3779 * empty entry. 3780 */ 3781 accents = 0; 3782 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3783 } 3784 /* 3785 * If the same accent key has been hit twice, 3786 * produce the accent char itself. 3787 */ 3788 if (action == accents) { 3789 action = accent_map.acc[accents - 1].accchar; 3790 accents = 0; 3791 if (metas) 3792 action |= MKEY; 3793 return (action); 3794 } 3795 /* remember the index and wait for the next key stroke */ 3796 accents = action; 3797 break; 3798 } 3799 if (accents > 0) { 3800 accents = 0; 3801 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3802 } 3803 if (action >= F_SCR && action <= L_SCR) { 3804 switch_scr(cur_console, action - F_SCR); 3805 break; 3806 } 3807 if (action >= F_FN && action <= L_FN) 3808 action |= FKEY; 3809 return(action); 3810 } 3811 } 3812 else { 3813 if (accents) { 3814 struct acc_t *acc; 3815 int i; 3816 3817 acc = &accent_map.acc[accents - 1]; 3818 accents = 0; 3819 /* 3820 * If the accent key is followed by the space key, 3821 * produce the accent char itself. 3822 */ 3823 if (action == ' ') { 3824 action = acc->accchar; 3825 if (metas) 3826 action |= MKEY; 3827 return (action); 3828 } 3829 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 3830 if (acc->map[i][0] == 0) /* end of the map entry */ 3831 break; 3832 if (acc->map[i][0] == action) { 3833 action = acc->map[i][1]; 3834 if (metas) 3835 action |= MKEY; 3836 return (action); 3837 } 3838 } 3839 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3840 goto next_code; 3841 } 3842 if (metas) 3843 action |= MKEY; 3844 return(action); 3845 } 3846 } 3847 goto next_code; 3848} 3849 3850int 3851scmmap(dev_t dev, int offset, int nprot) 3852{ 3853 if (offset > 0x20000 - PAGE_SIZE) 3854 return -1; 3855 return i386_btop((VIDEOMEM + offset)); 3856} 3857 3858/* 3859 * Calculate hardware attributes word using logical attributes mask and 3860 * hardware colors 3861 */ 3862 3863static int 3864mask2attr(struct term_stat *term) 3865{ 3866 int attr, mask = term->attr_mask; 3867 3868 if (mask & REVERSE_ATTR) { 3869 attr = ((mask & FOREGROUND_CHANGED) ? 3870 ((term->cur_color & 0xF000) >> 4) : 3871 (term->rev_color & 0x0F00)) | 3872 ((mask & BACKGROUND_CHANGED) ? 3873 ((term->cur_color & 0x0F00) << 4) : 3874 (term->rev_color & 0xF000)); 3875 } else 3876 attr = term->cur_color; 3877 3878 /* XXX: underline mapping for Hercules adapter can be better */ 3879 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3880 attr ^= 0x0800; 3881 if (mask & BLINK_ATTR) 3882 attr ^= 0x8000; 3883 3884 return attr; 3885} 3886 3887static void 3888set_keyboard(int command, int data) 3889{ 3890 int s; 3891 3892 if (sc_kbdc == NULL) 3893 return; 3894 3895 /* prevent the timeout routine from polling the keyboard */ 3896 if (!kbdc_lock(sc_kbdc, TRUE)) 3897 return; 3898 3899 /* disable the keyboard and mouse interrupt */ 3900 s = spltty(); 3901#if 0 3902 c = get_controller_command_byte(sc_kbdc); 3903 if ((c == -1) 3904 || !set_controller_command_byte(sc_kbdc, 3905 kbdc_get_device_mask(sc_kbdc), 3906 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 3907 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 3908 /* CONTROLLER ERROR */ 3909 kbdc_lock(sc_kbdc, FALSE); 3910 splx(s); 3911 return; 3912 } 3913 /* 3914 * Now that the keyboard controller is told not to generate 3915 * the keyboard and mouse interrupts, call `splx()' to allow 3916 * the other tty interrupts. The clock interrupt may also occur, 3917 * but the timeout routine (`scrn_timer()') will be blocked 3918 * by the lock flag set via `kbdc_lock()' 3919 */ 3920 splx(s); 3921#endif 3922 3923 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) 3924 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); 3925 3926#if 0 3927 /* restore the interrupts */ 3928 if (!set_controller_command_byte(sc_kbdc, 3929 kbdc_get_device_mask(sc_kbdc), 3930 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 3931 /* CONTROLLER ERROR */ 3932 } 3933#else 3934 splx(s); 3935#endif 3936 kbdc_lock(sc_kbdc, FALSE); 3937} 3938 3939static void 3940update_leds(int which) 3941{ 3942 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 3943 3944 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 3945 if (key_map.n_keys > ALTGR_OFFSET) { 3946 if (which & ALKED) 3947 which |= CLKED; 3948 else 3949 which &= ~CLKED; 3950 } 3951 3952 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); 3953} 3954 3955int 3956set_mode(scr_stat *scp) 3957{ 3958 video_info_t info; 3959 video_adapter_t *adp; 3960 3961 /* reject unsupported mode */ 3962 if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) 3963 return 1; 3964 3965 /* if this vty is not currently showing, do nothing */ 3966 if (scp != cur_console) 3967 return 0; 3968 3969 /* setup video hardware for the given mode */ 3970 adp = get_adapter(scp); 3971 (*biosvidsw.set_mode)(scp->adp, scp->mode); 3972 Crtat = (u_short *)adp->va_window; 3973 3974 if (!(scp->status & GRAPHICS_MODE)) { 3975 /* load appropriate font */ 3976 if (!(scp->status & PIXEL_MODE) 3977 && ISFONTAVAIL(get_adapter(scp)->va_flags)) { 3978 if (scp->font_size < 14) { 3979 if (fonts_loaded & FONT_8) 3980 copy_font(scp, LOAD, 8, font_8); 3981 } else if (scp->font_size >= 16) { 3982 if (fonts_loaded & FONT_16) 3983 copy_font(scp, LOAD, 16, font_16); 3984 } else { 3985 if (fonts_loaded & FONT_14) 3986 copy_font(scp, LOAD, 14, font_14); 3987 } 3988 /* 3989 * FONT KLUDGE: 3990 * This is an interim kludge to display correct font. 3991 * Always use the font page #0 on the video plane 2. 3992 * Somehow we cannot show the font in other font pages on 3993 * some video cards... XXX 3994 */ 3995 (*biosvidsw.show_font)(scp->adp, 0); 3996 } 3997 mark_all(scp); 3998 } 3999 4000 if (scp->status & PIXEL_MODE) 4001 generic_bzero((u_char *)(adp->va_window), scp->xpixel*scp->ypixel/8); 4002 set_border(scp, scp->border); 4003 4004 /* move hardware cursor out of the way */ 4005 (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); 4006 4007 return 0; 4008} 4009 4010void 4011set_border(scr_stat *scp, int color) 4012{ 4013 u_char *p; 4014 int xoff; 4015 int yoff; 4016 int xlen; 4017 int ylen; 4018 int i; 4019 4020 (*biosvidsw.set_border)(scp->adp, color); 4021 4022 if (scp->status & PIXEL_MODE) { 4023 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4024 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4025 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4026 outw(GDCIDX, 0xff08); /* bit mask */ 4027 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 4028 p = (u_char *)(get_adapter(scp)->va_window); 4029 xoff = scp->xoff; 4030 yoff = scp->yoff*scp->font_size; 4031 xlen = scp->xpixel/8; 4032 ylen = scp->ysize*scp->font_size; 4033 if (yoff > 0) { 4034 generic_bzero(p, xlen*yoff); 4035 generic_bzero(p + xlen*(yoff + ylen), 4036 xlen*scp->ypixel - xlen*(yoff + ylen)); 4037 } 4038 if (xoff > 0) { 4039 for (i = 0; i < ylen; ++i) { 4040 generic_bzero(p + xlen*(yoff + i), xoff); 4041 generic_bzero(p + xlen*(yoff + i) + xoff + scp->xsize, 4042 xlen - xoff - scp->xsize); 4043 } 4044 } 4045 outw(GDCIDX, 0x0000); /* set/reset */ 4046 outw(GDCIDX, 0x0001); /* set/reset enable */ 4047 } 4048} 4049 4050void 4051copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) 4052{ 4053 /* 4054 * FONT KLUDGE: 4055 * This is an interim kludge to display correct font. 4056 * Always use the font page #0 on the video plane 2. 4057 * Somehow we cannot show the font in other font pages on 4058 * some video cards... XXX 4059 */ 4060 font_loading_in_progress = TRUE; 4061 if (operation == LOAD) { 4062 (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256); 4063 if (sc_flags & CHAR_CURSOR) 4064 set_destructive_cursor(scp); 4065 } else if (operation == SAVE) { 4066 (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256); 4067 } 4068 font_loading_in_progress = FALSE; 4069} 4070 4071void 4072set_destructive_cursor(scr_stat *scp) 4073{ 4074 u_char cursor[32]; 4075 u_char *font_buffer; 4076 int font_size; 4077 int i; 4078 4079 if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp)) 4080 return; 4081 4082 if (scp->font_size < 14) { 4083 font_buffer = font_8; 4084 font_size = 8; 4085 } else if (scp->font_size >= 16) { 4086 font_buffer = font_16; 4087 font_size = 16; 4088 } else { 4089 font_buffer = font_14; 4090 font_size = 14; 4091 } 4092 4093 if (scp->status & MOUSE_VISIBLE) { 4094 if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) 4095 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 4096 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1) 4097 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 4098 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2) 4099 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 4100 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3) 4101 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 4102 else 4103 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 4104 cursor, scp->font_size); 4105 } 4106 else 4107 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 4108 cursor, scp->font_size); 4109 for (i=0; i<32; i++) 4110 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 4111 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 4112 cursor[i] |= 0xff; 4113#if 1 4114 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 4115#endif 4116 font_loading_in_progress = TRUE; 4117 (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); 4118 font_loading_in_progress = FALSE; 4119} 4120 4121void 4122sc_move_mouse(scr_stat *scp, int x, int y) 4123{ 4124 scp->mouse_xpos = x; 4125 scp->mouse_ypos = y; 4126 scp->mouse_pos = scp->mouse_oldpos = 4127 scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8; 4128} 4129 4130static void 4131set_mouse_pos(scr_stat *scp) 4132{ 4133 static int last_xpos = -1, last_ypos = -1; 4134 4135 if (scp->mouse_xpos < 0) 4136 scp->mouse_xpos = 0; 4137 if (scp->mouse_ypos < 0) 4138 scp->mouse_ypos = 0; 4139 if (!ISTEXTSC(scp)) { 4140 if (scp->mouse_xpos > scp->xpixel-1) 4141 scp->mouse_xpos = scp->xpixel-1; 4142 if (scp->mouse_ypos > scp->ypixel-1) 4143 scp->mouse_ypos = scp->ypixel-1; 4144 return; 4145 } 4146 if (scp->mouse_xpos > (scp->xsize*8)-1) 4147 scp->mouse_xpos = (scp->xsize*8)-1; 4148 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) 4149 scp->mouse_ypos = (scp->ysize*scp->font_size)-1; 4150 4151 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 4152 scp->status |= MOUSE_MOVED; 4153 4154 scp->mouse_pos = scp->scr_buf + 4155 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 4156 4157 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 4158 mouse_cut(scp); 4159 } 4160} 4161 4162#define isspace(c) (((c) & 0xff) == ' ') 4163 4164static int 4165skip_spc_right(scr_stat *scp, u_short *p) 4166{ 4167 int i; 4168 4169 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4170 if (!isspace(*p)) 4171 break; 4172 ++p; 4173 } 4174 return i; 4175} 4176 4177static int 4178skip_spc_left(scr_stat *scp, u_short *p) 4179{ 4180 int i; 4181 4182 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { 4183 if (!isspace(*p)) 4184 break; 4185 --p; 4186 } 4187 return i; 4188} 4189 4190static void 4191mouse_cut(scr_stat *scp) 4192{ 4193 u_short *end; 4194 u_short *p; 4195 int i = 0; 4196 int j = 0; 4197 4198 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? 4199 scp->mouse_pos + 1 : scp->mouse_pos; 4200 end = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4201 scp->mouse_cut_start : scp->mouse_cut_end; 4202 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4203 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { 4204 cut_buffer[i] = *p & 0xff; 4205 /* remember the position of the last non-space char */ 4206 if (!isspace(cut_buffer[i++])) 4207 j = i; 4208 /* trim trailing blank when crossing lines */ 4209 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 4210 cut_buffer[j++] = '\r'; 4211 i = j; 4212 } 4213 } 4214 cut_buffer[i] = '\0'; 4215 4216 /* scan towards the end of the last line */ 4217 --p; 4218 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4219 if (!isspace(*p)) 4220 break; 4221 ++p; 4222 } 4223 /* if there is nothing but blank chars, trim them, but mark towards eol */ 4224 if (i >= scp->xsize) { 4225 if (scp->mouse_cut_start > scp->mouse_cut_end) 4226 scp->mouse_cut_start = p; 4227 else 4228 scp->mouse_cut_end = p; 4229 cut_buffer[j++] = '\r'; 4230 cut_buffer[j] = '\0'; 4231 } 4232 4233 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 4234 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 4235} 4236 4237static void 4238mouse_cut_start(scr_stat *scp) 4239{ 4240 int i; 4241 4242 if (scp->status & MOUSE_VISIBLE) { 4243 if (scp->mouse_pos == scp->mouse_cut_start && 4244 scp->mouse_cut_start == scp->mouse_cut_end - 1) { 4245 cut_buffer[0] = '\0'; 4246 remove_cutmarking(scp); 4247 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 4248 /* if the pointer is on trailing blank chars, mark towards eol */ 4249 i = skip_spc_left(scp, scp->mouse_pos) + 1; 4250 scp->mouse_cut_start = scp->scr_buf + 4251 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; 4252 scp->mouse_cut_end = scp->scr_buf + 4253 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; 4254 cut_buffer[0] = '\r'; 4255 cut_buffer[1] = '\0'; 4256 scp->status |= MOUSE_CUTTING; 4257 } else { 4258 scp->mouse_cut_start = scp->mouse_pos; 4259 scp->mouse_cut_end = scp->mouse_cut_start + 1; 4260 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 4261 cut_buffer[1] = '\0'; 4262 scp->status |= MOUSE_CUTTING; 4263 } 4264 mark_all(scp); 4265 /* delete all other screens cut markings */ 4266 for (i=0; i<MAXCONS; i++) { 4267 if (console[i] == NULL || console[i] == scp) 4268 continue; 4269 remove_cutmarking(console[i]); 4270 } 4271 } 4272} 4273 4274static void 4275mouse_cut_end(scr_stat *scp) 4276{ 4277 if (scp->status & MOUSE_VISIBLE) { 4278 scp->status &= ~MOUSE_CUTTING; 4279 } 4280} 4281 4282static void 4283mouse_cut_word(scr_stat *scp) 4284{ 4285 u_short *p; 4286 u_short *sol; 4287 u_short *eol; 4288 int i; 4289 4290 /* 4291 * Because we don't have locale information in the kernel, 4292 * we only distinguish space char and non-space chars. Punctuation 4293 * chars, symbols and other regular chars are all treated alike. 4294 */ 4295 if (scp->status & MOUSE_VISIBLE) { 4296 sol = scp->scr_buf 4297 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4298 eol = sol + scp->xsize; 4299 if (isspace(*scp->mouse_pos)) { 4300 for (p = scp->mouse_pos; p >= sol; --p) 4301 if (!isspace(*p)) 4302 break; 4303 scp->mouse_cut_start = ++p; 4304 for (p = scp->mouse_pos; p < eol; ++p) 4305 if (!isspace(*p)) 4306 break; 4307 scp->mouse_cut_end = p; 4308 } else { 4309 for (p = scp->mouse_pos; p >= sol; --p) 4310 if (isspace(*p)) 4311 break; 4312 scp->mouse_cut_start = ++p; 4313 for (p = scp->mouse_pos; p < eol; ++p) 4314 if (isspace(*p)) 4315 break; 4316 scp->mouse_cut_end = p; 4317 } 4318 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4319 cut_buffer[i++] = *p & 0xff; 4320 cut_buffer[i] = '\0'; 4321 scp->status |= MOUSE_CUTTING; 4322 } 4323} 4324 4325static void 4326mouse_cut_line(scr_stat *scp) 4327{ 4328 u_short *p; 4329 int i; 4330 4331 if (scp->status & MOUSE_VISIBLE) { 4332 scp->mouse_cut_start = scp->scr_buf 4333 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4334 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; 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++] = '\r'; 4338 cut_buffer[i] = '\0'; 4339 scp->status |= MOUSE_CUTTING; 4340 } 4341} 4342 4343static void 4344mouse_cut_extend(scr_stat *scp) 4345{ 4346 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 4347 && (scp->mouse_cut_start != NULL)) { 4348 mouse_cut(scp); 4349 scp->status |= MOUSE_CUTTING; 4350 } 4351} 4352 4353static void 4354mouse_paste(scr_stat *scp) 4355{ 4356 if (scp->status & MOUSE_VISIBLE) { 4357 struct tty *tp; 4358 u_char *ptr = cut_buffer; 4359 4360 tp = VIRTUAL_TTY(get_scr_num()); 4361 while (*ptr) 4362 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 4363 } 4364} 4365 4366static void 4367draw_mouse_image(scr_stat *scp) 4368{ 4369 u_short buffer[32]; 4370 u_short xoffset, yoffset; 4371 u_short *crt_pos = (u_short *)(get_adapter(scp)->va_window) 4372 + (scp->mouse_pos - scp->scr_buf); 4373 u_char *font_buffer; 4374 int font_size; 4375 int i; 4376 4377 if (scp->font_size < 14) { 4378 font_buffer = font_8; 4379 font_size = 8; 4380 } else if (scp->font_size >= 16) { 4381 font_buffer = font_16; 4382 font_size = 16; 4383 } else { 4384 font_buffer = font_14; 4385 font_size = 14; 4386 } 4387 4388 xoffset = scp->mouse_xpos % 8; 4389 yoffset = scp->mouse_ypos % scp->font_size; 4390 4391 /* prepare mousepointer char's bitmaps */ 4392 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 4393 &scp->mouse_cursor[0], font_size); 4394 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 4395 &scp->mouse_cursor[32], font_size); 4396 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 4397 &scp->mouse_cursor[64], font_size); 4398 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 4399 &scp->mouse_cursor[96], font_size); 4400 for (i=0; i<font_size; i++) { 4401 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 4402 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 4403 } 4404 4405 /* now and-or in the mousepointer image */ 4406 for (i=0; i<16; i++) { 4407 buffer[i+yoffset] = 4408 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 4409 | (mouse_or_mask[i] >> xoffset); 4410 } 4411 for (i=0; i<font_size; i++) { 4412 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 4413 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 4414 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 4415 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 4416 } 4417 4418 scp->mouse_oldpos = scp->mouse_pos; 4419 4420#if 1 4421 /* wait for vertical retrace to avoid jitter on some videocards */ 4422 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 4423#endif 4424 font_loading_in_progress = TRUE; 4425 (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, 4426 SC_MOUSE_CHAR, 4); 4427 font_loading_in_progress = FALSE; 4428 4429 *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR; 4430 *(crt_pos+scp->xsize) = 4431 (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2); 4432 if (scp->mouse_xpos < (scp->xsize-1)*8) { 4433 *(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1); 4434 *(crt_pos+scp->xsize + 1) = 4435 (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3); 4436 } 4437 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 4438 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 4439} 4440 4441static void 4442remove_mouse_image(scr_stat *scp) 4443{ 4444 u_short *crt_pos; 4445 4446 if (!ISTEXTSC(scp)) 4447 return; 4448 4449 crt_pos = (u_short *)(get_adapter(scp)->va_window) 4450 + (scp->mouse_oldpos - scp->scr_buf); 4451 *(crt_pos) = *(scp->mouse_oldpos); 4452 *(crt_pos+1) = *(scp->mouse_oldpos+1); 4453 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 4454 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 4455 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 4456 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 4457} 4458 4459static void 4460draw_cutmarking(scr_stat *scp) 4461{ 4462 u_short *crt_pos; 4463 u_short *ptr; 4464 u_short och, nch; 4465 4466 crt_pos = (u_short *)(get_adapter(scp)->va_window); 4467 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 4468 nch = och = *(crt_pos + (ptr - scp->scr_buf)); 4469 /* are we outside the selected area ? */ 4470 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 4471 scp->mouse_cut_end : scp->mouse_cut_start) || 4472 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? 4473 scp->mouse_cut_start : scp->mouse_cut_end)) { 4474 if (ptr != scp->cursor_pos) 4475 nch = (och & 0xff) | (*ptr & 0xff00); 4476 } 4477 else { 4478 /* are we clear of the cursor image ? */ 4479 if (ptr != scp->cursor_pos) 4480 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 4481 else { 4482 if (sc_flags & CHAR_CURSOR) 4483 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 4484 else 4485 if (!(sc_flags & BLINK_CURSOR)) 4486 nch = (och & 0xff) | (*ptr & 0xff00); 4487 } 4488 } 4489 if (nch != och) 4490 *(crt_pos + (ptr - scp->scr_buf)) = nch; 4491 } 4492} 4493 4494static void 4495remove_cutmarking(scr_stat *scp) 4496{ 4497 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 4498 scp->status &= ~MOUSE_CUTTING; 4499 mark_all(scp); 4500} 4501 4502static void 4503do_bell(scr_stat *scp, int pitch, int duration) 4504{ 4505 if (cold || shutdown_in_progress) 4506 return; 4507 4508 if (scp != cur_console && (sc_flags & QUIET_BELL)) 4509 return; 4510 4511 if (sc_flags & VISUAL_BELL) { 4512 if (blink_in_progress) 4513 return; 4514 blink_in_progress = 4; 4515 if (scp != cur_console) 4516 blink_in_progress += 2; 4517 blink_screen(cur_console); 4518 } else { 4519 if (scp != cur_console) 4520 pitch *= 2; 4521 sysbeep(pitch, duration); 4522 } 4523} 4524 4525static void 4526blink_screen(void *arg) 4527{ 4528 scr_stat *scp = arg; 4529 4530 if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { 4531 blink_in_progress = FALSE; 4532 mark_all(scp); 4533 if (delayed_next_scr) 4534 switch_scr(scp, delayed_next_scr - 1); 4535 } 4536 else { 4537 if (blink_in_progress & 1) 4538 fillw(kernel_default.std_color | scr_map[0x20], 4539 (u_short *)(get_adapter(scp)->va_window), 4540 scp->xsize * scp->ysize); 4541 else 4542 fillw(kernel_default.rev_color | scr_map[0x20], 4543 (u_short *)(get_adapter(scp)->va_window), 4544 scp->xsize * scp->ysize); 4545 blink_in_progress--; 4546 timeout(blink_screen, scp, hz / 10); 4547 } 4548} 4549 4550void 4551sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) 4552{ 4553 u_char *font; 4554 u_char volatile *d; 4555 u_char *e; 4556 u_char *f; 4557 int font_size; 4558 int line_length; 4559 int xsize; 4560 u_short bg; 4561 int i, j; 4562 u_char c; 4563 4564 if (ISTEXTSC(scp)) { 4565 generic_bcopy(p + from, (u_short *)(get_adapter(scp)->va_window) + from, 4566 (to - from + 1)*sizeof(u_short)); 4567 } else /* if ISPIXELSC(scp) */ { 4568 if (mark) 4569 mark = 255; 4570 font_size = scp->font_size; 4571 if (font_size < 14) 4572 font = font_8; 4573 else if (font_size >= 16) 4574 font = font_16; 4575 else 4576 font = font_14; 4577 line_length = scp->xpixel/8; 4578 xsize = scp->xsize; 4579 d = (u_char *)(get_adapter(scp)->va_window) 4580 + scp->xoff + scp->yoff*font_size*line_length 4581 + (from%xsize) + font_size*line_length*(from/xsize); 4582 4583 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4584 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4585 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4586 bg = -1; 4587 for (i = from ; i <= to ; i++) { 4588 /* set background color in EGA/VGA latch */ 4589 if (bg != (p[i] & 0xf000)) { 4590 bg = (p[i] & 0xf000); 4591 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4592 outw(GDCIDX, 0xff08); /* bit mask */ 4593 *d = 0; 4594 c = *d; /* set the background color in the latch */ 4595 } 4596 /* foreground color */ 4597 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4598 e = (u_char *)d; 4599 f = &font[(p[i] & 0x00ff)*font_size]; 4600 for (j = 0 ; j < font_size; j++, f++) { 4601 outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */ 4602 *e = 0; 4603 e += line_length; 4604 } 4605 d++; 4606 if ((i % xsize) == xsize - 1) 4607 d += scp->xoff*2 + (font_size - 1)*line_length; 4608 } 4609 outw(GDCIDX, 0x0000); /* set/reset */ 4610 outw(GDCIDX, 0x0001); /* set/reset enable */ 4611 outw(GDCIDX, 0xff08); /* bit mask */ 4612 4613#if 0 /* VGA only */ 4614 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4615 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4616 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4617 outw(GDCIDX, 0xff08); /* bit mask */ 4618 bg = -1; 4619 for (i = from ; i <= to ; i++) { 4620 /* set background color in EGA/VGA latch */ 4621 if (bg != (p[i] & 0xf000)) { 4622 bg = (p[i] & 0xf000); 4623 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4624 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4625 *d = 0; 4626 c = *d; /* set the background color in the latch */ 4627 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4628 } 4629 /* foreground color */ 4630 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4631 e = (u_char *)d; 4632 f = &font[(p[i] & 0x00ff)*font_size]; 4633 for (j = 0 ; j < font_size; j++, f++) { 4634 *e = *f^mark; 4635 e += line_length; 4636 } 4637 d++; 4638 if ((i % xsize) == xsize - 1) 4639 d += scp->xoff*2 + (font_size - 1)*line_length; 4640 } 4641 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4642 outw(GDCIDX, 0x0000); /* set/reset */ 4643 outw(GDCIDX, 0x0001); /* set/reset enable */ 4644#endif /* 0 */ 4645 } 4646} 4647 4648#ifdef SC_SPLASH_SCREEN 4649 4650static void 4651scsplash_init(scr_stat *scp) 4652{ 4653 video_info_t info; 4654 4655 if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) { 4656 default_saver = scsplash_saver; 4657 scrn_blank_time = DEFAULT_BLANKTIME; 4658 run_scrn_saver = TRUE; 4659 if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) { 4660 scsplash_stick(TRUE); 4661 scsplash_saver(TRUE); 4662 } 4663 } 4664} 4665 4666static void 4667scsplash_term(scr_stat *scp) 4668{ 4669 default_saver = none_saver; 4670 scsplash_stick(FALSE); 4671 remove_scrn_saver(scsplash_saver); 4672 scsplash_unload(scp); 4673} 4674 4675static void 4676scsplash_saver(int show) 4677{ 4678 if (show) 4679 scsplash(TRUE); 4680 else if (!sticky_splash) 4681 scsplash(FALSE); 4682} 4683 4684#endif /* SC_SPLASH_SCREEN */ 4685 4686#endif /* NSC */ 4687