syscons.c revision 41004
1/*- 2 * Copyright (c) 1992-1998 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: syscons.c,v 1.286 1998/11/03 02:37:46 yokota Exp $ 29 */ 30 31#include "sc.h" 32#include "apm.h" 33#include "opt_ddb.h" 34#include "opt_devfs.h" 35#include "opt_vesa.h" 36#include "opt_vm86.h" 37#include "opt_syscons.h" 38 39#if NSC > 0 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/reboot.h> 43#include <sys/conf.h> 44#include <sys/proc.h> 45#include <sys/signalvar.h> 46#include <sys/tty.h> 47#include <sys/kernel.h> 48#include <sys/malloc.h> 49#ifdef DEVFS 50#include <sys/devfsext.h> 51#endif 52 53#include <machine/bootinfo.h> 54#include <machine/clock.h> 55#include <machine/cons.h> 56#include <machine/console.h> 57#include <machine/mouse.h> 58#include <machine/md_var.h> 59#include <machine/psl.h> 60#include <machine/frame.h> 61#include <machine/pc/display.h> 62#include <machine/pc/vesa.h> 63#include <machine/apm_bios.h> 64#include <machine/random.h> 65 66#include <vm/vm.h> 67#include <vm/vm_param.h> 68#include <vm/pmap.h> 69 70#include <i386/isa/isa.h> 71#include <i386/isa/isa_device.h> 72#include <i386/isa/timerreg.h> 73#include <i386/isa/kbdtables.h> 74#include <i386/isa/kbdio.h> 75#include <i386/isa/videoio.h> 76#include <i386/isa/syscons.h> 77 78#if !defined(MAXCONS) 79#define MAXCONS 16 80#endif 81 82#if !defined(SC_MAX_HISTORY_SIZE) 83#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS) 84#endif 85 86#if !defined(SC_HISTORY_SIZE) 87#define SC_HISTORY_SIZE (ROW * 4) 88#endif 89 90#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE 91#undef SC_MAX_HISTORY_SIZE 92#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS) 93#endif 94 95#if !defined(SC_MOUSE_CHAR) 96#define SC_MOUSE_CHAR (0xd0) 97#endif 98 99#define COLD 0 100#define WARM 1 101 102#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ 103#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ 104 105/* for backward compatibility */ 106#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 107 108typedef struct old_mouse_data { 109 int x; 110 int y; 111 int buttons; 112} old_mouse_data_t; 113 114typedef struct old_mouse_info { 115 int operation; 116 union { 117 struct old_mouse_data data; 118 struct mouse_mode mode; 119 } u; 120} old_mouse_info_t; 121 122/* XXX use sc_bcopy where video memory is concerned */ 123extern void generic_bcopy(const void *, void *, size_t); 124extern void generic_bzero(void *, size_t); 125 126static default_attr user_default = { 127 (FG_LIGHTGREY | BG_BLACK) << 8, 128 (FG_BLACK | BG_LIGHTGREY) << 8 129}; 130 131static default_attr kernel_default = { 132 (FG_WHITE | BG_BLACK) << 8, 133 (FG_BLACK | BG_LIGHTGREY) << 8 134}; 135 136static scr_stat main_console; 137static scr_stat *console[MAXCONS]; 138#ifdef DEVFS 139static void *sc_devfs_token[MAXCONS]; 140static void *sc_mouse_devfs_token; 141static void *sc_console_devfs_token; 142#endif 143 scr_stat *cur_console; 144static scr_stat *new_scp, *old_scp; 145static term_stat kernel_console; 146static default_attr *current_default; 147static int sc_flags; 148static int sc_port = IO_KBD; 149static KBDC sc_kbdc = NULL; 150static char init_done = COLD; 151static u_short sc_buffer[ROW*COL]; 152static char shutdown_in_progress = FALSE; 153static char font_loading_in_progress = FALSE; 154static char switch_in_progress = FALSE; 155static char write_in_progress = FALSE; 156static char blink_in_progress = FALSE; 157static int blinkrate = 0; 158 u_int crtc_addr = MONO_BASE; 159 char crtc_type = KD_MONO; 160static char crtc_vga = FALSE; 161static int adp_flags; 162static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 163static u_char accents = 0; 164static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 165static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 166static int delayed_next_scr = FALSE; 167static long scrn_blank_time = 0; /* screen saver timeout value */ 168 int scrn_blanked = 0; /* screen saver active flag */ 169static long scrn_time_stamp; 170static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */ 171static int run_scrn_saver = FALSE; /* should run the saver? */ 172static int scrn_idle = FALSE; /* about to run the saver */ 173 u_char scr_map[256]; 174 u_char scr_rmap[256]; 175static int initial_video_mode; /* initial video mode # */ 176static int bios_video_mode; /* video mode # set by BIOS */ 177 int fonts_loaded = 0 178#ifdef STD8X16FONT 179 | FONT_16 180#endif 181 ; 182 183 u_char font_8[256*8]; 184 u_char font_14[256*14]; 185#ifdef STD8X16FONT 186extern 187#endif 188 u_char font_16[256*16]; 189 u_char palette[256*3]; 190static u_char *cut_buffer; 191static int cut_buffer_size; 192static int mouse_level; /* sysmouse protocol level */ 193static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; 194static u_short mouse_and_mask[16] = { 195 0xc000, 0xe000, 0xf000, 0xf800, 196 0xfc00, 0xfe00, 0xff00, 0xff80, 197 0xfe00, 0x1e00, 0x1f00, 0x0f00, 198 0x0f00, 0x0000, 0x0000, 0x0000 199 }; 200static u_short mouse_or_mask[16] = { 201 0x0000, 0x4000, 0x6000, 0x7000, 202 0x7800, 0x7c00, 0x7e00, 0x6800, 203 0x0c00, 0x0c00, 0x0600, 0x0600, 204 0x0000, 0x0000, 0x0000, 0x0000 205 }; 206 207 int sc_history_size = SC_HISTORY_SIZE; 208static int extra_history_size = 209 SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; 210 211static void none_saver(int blank) { } 212static void (*current_saver)(int blank) = none_saver; 213static void (*default_saver)(int blank) = none_saver; 214 d_ioctl_t *sc_user_ioctl; 215 216static int sticky_splash = FALSE; 217 218/* OS specific stuff */ 219#ifdef not_yet_done 220#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 221struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 222struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) 223struct tty *sccons[MAXCONS+2]; 224#else 225#define VIRTUAL_TTY(x) &sccons[x] 226#define CONSOLE_TTY &sccons[MAXCONS] 227#define MOUSE_TTY &sccons[MAXCONS+1] 228static struct tty sccons[MAXCONS+2]; 229#endif 230#define SC_MOUSE 128 231#define SC_CONSOLE 255 232u_short *Crtat; 233static const int nsccons = MAXCONS+2; 234 235#define WRAPHIST(scp, pointer, offset)\ 236 ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ 237 + (offset)) % (scp)->history_size)) 238#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 239 240/* prototypes */ 241static int scattach(struct isa_device *dev); 242static ointhand2_t scintr; 243static int scparam(struct tty *tp, struct termios *t); 244static int scprobe(struct isa_device *dev); 245static int scvidprobe(int unit, int flags); 246static int sckbdprobe(int unit, int flags); 247static void scstart(struct tty *tp); 248static void scmousestart(struct tty *tp); 249static void scinit(void); 250static void scshutdown(int howto, void *arg); 251static u_int scgetc(u_int flags); 252#define SCGETC_CN 1 253#define SCGETC_NONBLOCK 2 254static void sccnupdate(scr_stat *scp); 255static scr_stat *alloc_scp(void); 256static void init_scp(scr_stat *scp); 257static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); 258static int get_scr_num(void); 259static timeout_t scrn_timer; 260static void scrn_update(scr_stat *scp, int show_cursor); 261static void scrn_saver(void (*saver)(int), int blank); 262static void stop_scrn_saver(void (*saver)(int)); 263static int wait_scrn_saver_stop(void); 264static int switch_scr(scr_stat *scp, u_int next_scr); 265static void exchange_scr(void); 266static void scan_esc(scr_stat *scp, u_char c); 267static void ansi_put(scr_stat *scp, u_char *buf, int len); 268static void draw_cursor_image(scr_stat *scp); 269static void remove_cursor_image(scr_stat *scp); 270static void move_crsr(scr_stat *scp, int x, int y); 271static u_char *get_fstr(u_int c, u_int *len); 272static void history_to_screen(scr_stat *scp); 273static int history_up_line(scr_stat *scp); 274static int history_down_line(scr_stat *scp); 275static int mask2attr(struct term_stat *term); 276static void set_keyboard(int command, int data); 277static void update_leds(int which); 278static void set_destructive_cursor(scr_stat *scp); 279static void set_mouse_pos(scr_stat *scp); 280static int skip_spc_right(scr_stat *scp, u_short *p); 281static int skip_spc_left(scr_stat *scp, u_short *p); 282static void mouse_cut(scr_stat *scp); 283static void mouse_cut_start(scr_stat *scp); 284static void mouse_cut_end(scr_stat *scp); 285static void mouse_cut_word(scr_stat *scp); 286static void mouse_cut_line(scr_stat *scp); 287static void mouse_cut_extend(scr_stat *scp); 288static void mouse_paste(scr_stat *scp); 289static void draw_mouse_image(scr_stat *scp); 290static void remove_mouse_image(scr_stat *scp); 291static void draw_cutmarking(scr_stat *scp); 292static void remove_cutmarking(scr_stat *scp); 293static void do_bell(scr_stat *scp, int pitch, int duration); 294static timeout_t blink_screen; 295#ifdef SC_SPLASH_SCREEN 296static void scsplash_init(scr_stat *scp); 297static void scsplash_term(scr_stat *scp); 298static void scsplash_saver(int show); 299#define scsplash_stick(stick) (sticky_splash = (stick)) 300#else 301#define scsplash_stick(stick) 302#endif 303 304struct isa_driver scdriver = { 305 scprobe, scattach, "sc", 1 306}; 307 308static d_open_t scopen; 309static d_close_t scclose; 310static d_read_t scread; 311static d_write_t scwrite; 312static d_ioctl_t scioctl; 313static d_mmap_t scmmap; 314 315#define CDEV_MAJOR 12 316static struct cdevsw sc_cdevsw = { 317 scopen, scclose, scread, scwrite, 318 scioctl, nullstop, noreset, scdevtotty, 319 ttpoll, scmmap, nostrategy, "sc", 320 NULL, -1, nodump, nopsize, 321 D_TTY, 322}; 323 324static void 325draw_cursor_image(scr_stat *scp) 326{ 327 u_short cursor_image; 328 u_short *ptr; 329 u_short prev_image; 330 331 if (ISPIXELSC(scp)) { 332 sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 333 scp->cursor_pos - scp->scr_buf, 1); 334 return; 335 } 336 337 ptr = (u_short *)(get_adapter(scp)->va_window) 338 + (scp->cursor_pos - scp->scr_buf); 339 340 /* do we have a destructive cursor ? */ 341 if (sc_flags & CHAR_CURSOR) { 342 prev_image = scp->cursor_saveunder; 343 cursor_image = *ptr & 0x00ff; 344 if (cursor_image == DEAD_CHAR) 345 cursor_image = prev_image & 0x00ff; 346 cursor_image |= *(scp->cursor_pos) & 0xff00; 347 scp->cursor_saveunder = cursor_image; 348 /* update the cursor bitmap if the char under the cursor has changed */ 349 if (prev_image != cursor_image) 350 set_destructive_cursor(scp); 351 /* modify cursor_image */ 352 if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 353 /* 354 * When the mouse pointer is at the same position as the cursor, 355 * the cursor bitmap needs to be updated even if the char under 356 * the cursor hasn't changed, because the mouse pionter may 357 * have moved by a few dots within the cursor cel. 358 */ 359 if ((prev_image == cursor_image) 360 && (cursor_image != *(scp->cursor_pos))) 361 set_destructive_cursor(scp); 362 cursor_image &= 0xff00; 363 cursor_image |= DEAD_CHAR; 364 } 365 } else { 366 cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; 367 scp->cursor_saveunder = cursor_image; 368 if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 369 if ((cursor_image & 0x7000) == 0x7000) { 370 cursor_image &= 0x8fff; 371 if(!(cursor_image & 0x0700)) 372 cursor_image |= 0x0700; 373 } else { 374 cursor_image |= 0x7000; 375 if ((cursor_image & 0x0700) == 0x0700) 376 cursor_image &= 0xf0ff; 377 } 378 } 379 } 380 *ptr = cursor_image; 381} 382 383static void 384remove_cursor_image(scr_stat *scp) 385{ 386 if (ISPIXELSC(scp)) 387 sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 388 scp->cursor_oldpos - scp->scr_buf, 0); 389 else 390 *((u_short *)(get_adapter(scp)->va_window) 391 + (scp->cursor_oldpos - scp->scr_buf)) 392 = scp->cursor_saveunder; 393} 394 395static void 396move_crsr(scr_stat *scp, int x, int y) 397{ 398 if (x < 0) 399 x = 0; 400 if (y < 0) 401 y = 0; 402 if (x >= scp->xsize) 403 x = scp->xsize-1; 404 if (y >= scp->ysize) 405 y = scp->ysize-1; 406 scp->xpos = x; 407 scp->ypos = y; 408 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 409} 410 411static int 412scprobe(struct isa_device *dev) 413{ 414 if (!scvidprobe(dev->id_unit, dev->id_flags)) { 415 if (bootverbose) 416 printf("sc%d: no video adapter is found.\n", dev->id_unit); 417 return (0); 418 } 419 420#if defined(VESA) && defined(VM86) 421 if (vesa_load()) 422 return FALSE; 423#endif 424 425 (*biosvidsw.diag)(bootverbose); 426 427 sc_port = dev->id_iobase; 428 if (sckbdprobe(dev->id_unit, dev->id_flags)) 429 return (IO_KBDSIZE); 430 else 431 return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); 432} 433 434/* probe video adapters, return TRUE if found */ 435static int 436scvidprobe(int unit, int flags) 437{ 438 video_adapter_t *adp; 439 440 /* do this test only once */ 441 if (init_done != COLD) 442 return (crtc_type != -1); 443 444 if ((*biosvidsw.init)() <= 0) 445 return FALSE; 446 if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL) 447 return FALSE; 448 449 crtc_type = adp->va_type; 450 crtc_vga = (crtc_type == KD_VGA); 451 crtc_addr = adp->va_crtc_addr; 452 Crtat = (u_short *)adp->va_window; 453 adp_flags = adp->va_flags; 454 initial_video_mode = adp->va_initial_mode; 455 bios_video_mode = adp->va_initial_bios_mode; 456 457 return TRUE; 458} 459 460/* probe the keyboard, return TRUE if found */ 461static int 462sckbdprobe(int unit, int flags) 463{ 464 int codeset; 465 int c = -1; 466 int m; 467 int res, id; 468 469 sc_kbdc = kbdc_open(sc_port); 470 471 if (!kbdc_lock(sc_kbdc, TRUE)) { 472 /* driver error? */ 473 printf("sc%d: unable to lock the controller.\n", unit); 474 return ((flags & DETECT_KBD) ? FALSE : TRUE); 475 } 476 477 /* flush any noise in the buffer */ 478 empty_both_buffers(sc_kbdc, 10); 479 480 /* save the current keyboard controller command byte */ 481 m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; 482 c = get_controller_command_byte(sc_kbdc); 483 if (c == -1) { 484 /* CONTROLLER ERROR */ 485 printf("sc%d: unable to get the current command byte value.\n", unit); 486 goto fail; 487 } 488 if (bootverbose) 489 printf("sc%d: the current keyboard controller command byte %04x\n", 490 unit, c); 491#if 0 492 /* override the keyboard lock switch */ 493 c |= KBD_OVERRIDE_KBD_LOCK; 494#endif 495 496 /* 497 * The keyboard may have been screwed up by the boot block. 498 * We may just be able to recover from error by testing the controller 499 * and the keyboard port. The controller command byte needs to be saved 500 * before this recovery operation, as some controllers seem to set 501 * the command byte to particular values. 502 */ 503 test_controller(sc_kbdc); 504 test_kbd_port(sc_kbdc); 505 506 /* enable the keyboard port, but disable the keyboard intr. */ 507 if (!set_controller_command_byte(sc_kbdc, 508 KBD_KBD_CONTROL_BITS, 509 KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { 510 /* CONTROLLER ERROR 511 * there is very little we can do... 512 */ 513 printf("sc%d: unable to set the command byte.\n", unit); 514 goto fail; 515 } 516 517 /* 518 * Check if we have an XT keyboard before we attempt to reset it. 519 * The procedure assumes that the keyboard and the controller have 520 * been set up properly by BIOS and have not been messed up 521 * during the boot process. 522 */ 523 codeset = -1; 524 if (flags & XT_KEYBD) 525 /* the user says there is a XT keyboard */ 526 codeset = 1; 527#ifdef DETECT_XT_KEYBOARD 528 else if ((c & KBD_TRANSLATION) == 0) { 529 /* SET_SCANCODE_SET is not always supported; ignore error */ 530 if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) 531 == KBD_ACK) 532 codeset = read_kbd_data(sc_kbdc); 533 } 534 if (bootverbose) 535 printf("sc%d: keyboard scancode set %d\n", unit, codeset); 536#endif /* DETECT_XT_KEYBOARD */ 537 538 if (flags & KBD_NORESET) { 539 write_kbd_command(sc_kbdc, KBDC_ECHO); 540 if (read_kbd_data(sc_kbdc) != KBD_ECHO) { 541 empty_both_buffers(sc_kbdc, 10); 542 test_controller(sc_kbdc); 543 test_kbd_port(sc_kbdc); 544 if (bootverbose) 545 printf("sc%d: failed to get response from the keyboard.\n", 546 unit); 547 goto fail; 548 } 549 } else { 550 /* reset keyboard hardware */ 551 if (!reset_kbd(sc_kbdc)) { 552 /* KEYBOARD ERROR 553 * Keyboard reset may fail either because the keyboard doen't 554 * exist, or because the keyboard doesn't pass the self-test, 555 * or the keyboard controller on the motherboard and the keyboard 556 * somehow fail to shake hands. It is just possible, particularly 557 * in the last case, that the keyoard controller may be left 558 * in a hung state. test_controller() and test_kbd_port() appear 559 * to bring the keyboard controller back (I don't know why and 560 * how, though.) 561 */ 562 empty_both_buffers(sc_kbdc, 10); 563 test_controller(sc_kbdc); 564 test_kbd_port(sc_kbdc); 565 /* We could disable the keyboard port and interrupt... but, 566 * the keyboard may still exist (see above). 567 */ 568 if (bootverbose) 569 printf("sc%d: failed to reset the keyboard.\n", unit); 570 goto fail; 571 } 572 } 573 574 /* 575 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards 576 * such as those on the IBM ThinkPad laptop computers can be used 577 * with the standard console driver. 578 */ 579 if (codeset == 1) { 580 if (send_kbd_command_and_data( 581 sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 582 /* XT kbd doesn't need scan code translation */ 583 c &= ~KBD_TRANSLATION; 584 } else { 585 /* KEYBOARD ERROR 586 * The XT kbd isn't usable unless the proper scan code set 587 * is selected. 588 */ 589 printf("sc%d: unable to set the XT keyboard mode.\n", unit); 590 goto fail; 591 } 592 } 593 /* enable the keyboard port and intr. */ 594 if (!set_controller_command_byte(sc_kbdc, 595 KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 596 (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 597 | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 598 /* CONTROLLER ERROR 599 * This is serious; we are left with the disabled keyboard intr. 600 */ 601 printf("sc%d: unable to enable the keyboard port and intr.\n", unit); 602 goto fail; 603 } 604 605 /* Get the ID of the keyboard, if any */ 606 empty_kbd_buffer(sc_kbdc, 5); 607 res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID); 608 if (res == KBD_ACK) { 609 /* 10ms delay */ 610 DELAY(10000); 611 id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc); 612 if (bootverbose) 613 printf("sc%d: keyboard device ID: %04x\n", unit, id); 614 } 615 616 kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), 617 kbdc_lock(sc_kbdc, FALSE); 618 return TRUE; 619 620fail: 621 if (c != -1) 622 /* try to restore the command byte as before, if possible */ 623 set_controller_command_byte(sc_kbdc, 0xff, c); 624 kbdc_set_device_mask(sc_kbdc, 625 (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); 626 kbdc_lock(sc_kbdc, FALSE); 627 return FALSE; 628} 629 630#if NAPM > 0 631static int 632scresume(void *dummy) 633{ 634 shfts = ctls = alts = agrs = metas = accents = 0; 635 return 0; 636} 637#endif 638 639static int 640scattach(struct isa_device *dev) 641{ 642 scr_stat *scp; 643 video_info_t info; 644 dev_t cdev = makedev(CDEV_MAJOR, 0); 645#ifdef DEVFS 646 int vc; 647#endif 648 649 dev->id_ointr = scintr; 650 scinit(); 651 sc_flags = dev->id_flags; 652 if (!ISFONTAVAIL(adp_flags)) 653 sc_flags &= ~CHAR_CURSOR; 654 655 scp = console[0]; 656 657 /* copy temporary buffer to final buffer */ 658 scp->scr_buf = NULL; 659 sc_alloc_scr_buffer(scp, FALSE, FALSE); 660 bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short)); 661 662 /* cut buffer is available only when the mouse pointer is used */ 663 if (ISMOUSEAVAIL(adp_flags)) 664 sc_alloc_cut_buffer(scp, FALSE); 665 666 /* initialize history buffer & pointers */ 667 sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); 668 669#if defined(VESA) && defined(VM86) 670 if ((sc_flags & VESA800X600) 671 && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { 672#ifdef SC_SPLASH_SCREEN 673 scsplash_term(scp); 674#endif 675 sc_set_graphics_mode(scp, NULL, M_VESA_800x600); 676 sc_set_pixel_mode(scp, NULL, COL, ROW, 16); 677 initial_video_mode = M_VESA_800x600; 678#ifdef SC_SPLASH_SCREEN 679 scsplash_init(scp); 680#endif 681 } 682#endif /* VESA && VM86 */ 683 684 /* initialize cursor stuff */ 685 if (!ISGRAPHSC(scp)) 686 draw_cursor_image(scp); 687 688 /* get screen update going */ 689 scrn_timer((void *)TRUE); 690 691 update_leds(scp->status); 692 693 printf("sc%d: ", dev->id_unit); 694 switch(crtc_type) { 695 case KD_VGA: 696 printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); 697 break; 698 case KD_EGA: 699 printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); 700 break; 701 case KD_CGA: 702 printf("CGA"); 703 break; 704 case KD_MONO: 705 case KD_HERCULES: 706 default: 707 printf("MDA/Hercules"); 708 break; 709 } 710 printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, sc_flags); 711 712#if NAPM > 0 713 scp->r_hook.ah_fun = scresume; 714 scp->r_hook.ah_arg = NULL; 715 scp->r_hook.ah_name = "system keyboard"; 716 scp->r_hook.ah_order = APM_MID_ORDER; 717 apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 718#endif 719 720 at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC); 721 722 cdevsw_add(&cdev, &sc_cdevsw, NULL); 723 724#ifdef DEVFS 725 for (vc = 0; vc < MAXCONS; vc++) 726 sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR, 727 UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc); 728 sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR, 729 UID_ROOT, GID_WHEEL, 0600, "sysmouse"); 730 sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR, 731 UID_ROOT, GID_WHEEL, 0600, "consolectl"); 732#endif 733 return 0; 734} 735 736struct tty 737*scdevtotty(dev_t dev) 738{ 739 int unit = minor(dev); 740 741 if (init_done == COLD) 742 return(NULL); 743 if (unit == SC_CONSOLE) 744 return CONSOLE_TTY; 745 if (unit == SC_MOUSE) 746 return MOUSE_TTY; 747 if (unit >= MAXCONS || unit < 0) 748 return(NULL); 749 return VIRTUAL_TTY(unit); 750} 751 752int 753scopen(dev_t dev, int flag, int mode, struct proc *p) 754{ 755 struct tty *tp = scdevtotty(dev); 756 757 if (!tp) 758 return(ENXIO); 759 760 tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; 761 tp->t_param = scparam; 762 tp->t_dev = dev; 763 if (!(tp->t_state & TS_ISOPEN)) { 764 ttychars(tp); 765 /* Use the current setting of the <-- key as default VERASE. */ 766 /* If the Delete key is preferable, an stty is necessary */ 767 tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; 768 tp->t_iflag = TTYDEF_IFLAG; 769 tp->t_oflag = TTYDEF_OFLAG; 770 tp->t_cflag = TTYDEF_CFLAG; 771 tp->t_lflag = TTYDEF_LFLAG; 772 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 773 scparam(tp, &tp->t_termios); 774 (*linesw[tp->t_line].l_modem)(tp, 1); 775 if (minor(dev) == SC_MOUSE) 776 mouse_level = 0; /* XXX */ 777 } 778 else 779 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 780 return(EBUSY); 781 if (minor(dev) < MAXCONS && !console[minor(dev)]) { 782 console[minor(dev)] = alloc_scp(); 783 if (ISGRAPHSC(console[minor(dev)])) 784 sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16); 785 } 786 if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 787 tp->t_winsize.ws_col = console[minor(dev)]->xsize; 788 tp->t_winsize.ws_row = console[minor(dev)]->ysize; 789 } 790 return ((*linesw[tp->t_line].l_open)(dev, tp)); 791} 792 793int 794scclose(dev_t dev, int flag, int mode, struct proc *p) 795{ 796 struct tty *tp = scdevtotty(dev); 797 struct scr_stat *scp; 798 799 if (!tp) 800 return(ENXIO); 801 if (minor(dev) < MAXCONS) { 802 scp = sc_get_scr_stat(tp->t_dev); 803 if (scp->status & SWITCH_WAIT_ACQ) 804 wakeup((caddr_t)&scp->smode); 805#if not_yet_done 806 if (scp == &main_console) { 807 scp->pid = 0; 808 scp->proc = NULL; 809 scp->smode.mode = VT_AUTO; 810 } 811 else { 812 free(scp->scr_buf, M_DEVBUF); 813 if (scp->history != NULL) { 814 free(scp->history, M_DEVBUF); 815 if (scp->history_size / scp->xsize 816 > imax(sc_history_size, scp->ysize)) 817 extra_history_size += scp->history_size / scp->xsize 818 - imax(sc_history_size, scp->ysize); 819 } 820 free(scp, M_DEVBUF); 821 console[minor(dev)] = NULL; 822 } 823#else 824 scp->pid = 0; 825 scp->proc = NULL; 826 scp->smode.mode = VT_AUTO; 827#endif 828 } 829 spltty(); 830 (*linesw[tp->t_line].l_close)(tp, flag); 831 ttyclose(tp); 832 spl0(); 833 return(0); 834} 835 836int 837scread(dev_t dev, struct uio *uio, int flag) 838{ 839 struct tty *tp = scdevtotty(dev); 840 841 if (!tp) 842 return(ENXIO); 843 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 844} 845 846int 847scwrite(dev_t dev, struct uio *uio, int flag) 848{ 849 struct tty *tp = scdevtotty(dev); 850 851 if (!tp) 852 return(ENXIO); 853 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 854} 855 856static void 857scintr(int unit) 858{ 859 static struct tty *cur_tty; 860 int c, len; 861 u_char *cp; 862 863 /* 864 * Loop while there is still input to get from the keyboard. 865 * I don't think this is nessesary, and it doesn't fix 866 * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 867 */ 868 while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { 869 870 cur_tty = VIRTUAL_TTY(get_scr_num()); 871 if (!(cur_tty->t_state & TS_ISOPEN)) 872 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 873 continue; 874 875 switch (c & 0xff00) { 876 case 0x0000: /* normal key */ 877 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 878 break; 879 case FKEY: /* function key, return string */ 880 if (cp = get_fstr((u_int)c, (u_int *)&len)) { 881 while (len-- > 0) 882 (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 883 } 884 break; 885 case MKEY: /* meta is active, prepend ESC */ 886 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 887 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 888 break; 889 case BKEY: /* backtab fixed sequence (esc [ Z) */ 890 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 891 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 892 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 893 break; 894 } 895 } 896 897#if 0 898 if (cur_console->status & MOUSE_ENABLED) { 899 cur_console->status &= ~MOUSE_VISIBLE; 900 remove_mouse_image(cur_console); 901 } 902#else 903 if (cur_console->status & MOUSE_VISIBLE) { 904 remove_mouse_image(cur_console); 905 cur_console->status &= ~MOUSE_VISIBLE; 906 } 907#endif 908} 909 910static int 911scparam(struct tty *tp, struct termios *t) 912{ 913 tp->t_ispeed = t->c_ispeed; 914 tp->t_ospeed = t->c_ospeed; 915 tp->t_cflag = t->c_cflag; 916 return 0; 917} 918 919int 920scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 921{ 922 u_int delta_ehs; 923 int error; 924 int i; 925 struct tty *tp; 926 scr_stat *scp; 927 video_adapter_t *adp; 928 int s; 929 930 tp = scdevtotty(dev); 931 if (!tp) 932 return ENXIO; 933 scp = sc_get_scr_stat(tp->t_dev); 934 935 /* If there is a user_ioctl function call that first */ 936 if (sc_user_ioctl) { 937 error = (*sc_user_ioctl)(dev, cmd, data, flag, p); 938 if (error != ENOIOCTL) 939 return error; 940 } 941 942 error = sc_vid_ioctl(tp, cmd, data, flag, p); 943 if (error != ENOIOCTL) 944 return error; 945 946 switch (cmd) { /* process console hardware related ioctl's */ 947 948 case GIO_ATTR: /* get current attributes */ 949 *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 950 return 0; 951 952 case GIO_COLOR: /* is this a color console ? */ 953 *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0; 954 return 0; 955 956 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 957 if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) 958 return EINVAL; 959 s = spltty(); 960 scrn_blank_time = *(int *)data; 961 run_scrn_saver = (scrn_blank_time != 0); 962 splx(s); 963 return 0; 964 965 case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 966 if ((*(int*)data) & 0x01) 967 sc_flags |= BLINK_CURSOR; 968 else 969 sc_flags &= ~BLINK_CURSOR; 970 if ((*(int*)data) & 0x02) { 971 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 972 return ENXIO; 973 sc_flags |= CHAR_CURSOR; 974 } else 975 sc_flags &= ~CHAR_CURSOR; 976 /* 977 * The cursor shape is global property; all virtual consoles 978 * are affected. Update the cursor in the current console... 979 */ 980 if (!ISGRAPHSC(cur_console)) { 981 s = spltty(); 982 remove_cursor_image(cur_console); 983 if (sc_flags & CHAR_CURSOR) 984 set_destructive_cursor(cur_console); 985 draw_cursor_image(cur_console); 986 splx(s); 987 } 988 return 0; 989 990 case CONS_BELLTYPE: /* set bell type sound/visual */ 991 if ((*(int *)data) & 0x01) 992 sc_flags |= VISUAL_BELL; 993 else 994 sc_flags &= ~VISUAL_BELL; 995 if ((*(int *)data) & 0x02) 996 sc_flags |= QUIET_BELL; 997 else 998 sc_flags &= ~QUIET_BELL; 999 return 0; 1000 1001 case CONS_HISTORY: /* set history size */ 1002 if (*(int *)data > 0) { 1003 int lines; /* buffer size to allocate */ 1004 int lines0; /* current buffer size */ 1005 1006 lines = imax(*(int *)data, scp->ysize); 1007 lines0 = (scp->history != NULL) ? 1008 scp->history_size / scp->xsize : scp->ysize; 1009 if (lines0 > imax(sc_history_size, scp->ysize)) 1010 delta_ehs = lines0 - imax(sc_history_size, scp->ysize); 1011 else 1012 delta_ehs = 0; 1013 /* 1014 * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE 1015 * lines or scp->ysize lines, whichever is larger. A value 1016 * greater than that is allowed, subject to extra_history_size. 1017 */ 1018 if (lines > imax(sc_history_size, scp->ysize)) 1019 if (lines - imax(sc_history_size, scp->ysize) > 1020 extra_history_size + delta_ehs) 1021 return EINVAL; 1022 if (cur_console->status & BUFFER_SAVED) 1023 return EBUSY; 1024 sc_alloc_history_buffer(scp, lines, delta_ehs, TRUE); 1025 return 0; 1026 } 1027 else 1028 return EINVAL; 1029 1030 case CONS_MOUSECTL: /* control mouse arrow */ 1031 case OLD_CONS_MOUSECTL: 1032 { 1033 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 1034 static int butmap[8] = { 1035 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1036 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1037 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 1038 MOUSE_MSC_BUTTON3UP, 1039 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 1040 MOUSE_MSC_BUTTON2UP, 1041 MOUSE_MSC_BUTTON1UP, 1042 0, 1043 }; 1044 mouse_info_t *mouse = (mouse_info_t*)data; 1045 mouse_info_t buf; 1046 1047 /* FIXME: */ 1048 if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags)) 1049 return ENODEV; 1050 1051 if (cmd == OLD_CONS_MOUSECTL) { 1052 static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 1053 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 1054 1055 mouse = &buf; 1056 mouse->operation = old_mouse->operation; 1057 switch (mouse->operation) { 1058 case MOUSE_MODE: 1059 mouse->u.mode = old_mouse->u.mode; 1060 break; 1061 case MOUSE_SHOW: 1062 case MOUSE_HIDE: 1063 break; 1064 case MOUSE_MOVEABS: 1065 case MOUSE_MOVEREL: 1066 case MOUSE_ACTION: 1067 mouse->u.data.x = old_mouse->u.data.x; 1068 mouse->u.data.y = old_mouse->u.data.y; 1069 mouse->u.data.z = 0; 1070 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 1071 break; 1072 case MOUSE_GETINFO: 1073 old_mouse->u.data.x = scp->mouse_xpos; 1074 old_mouse->u.data.y = scp->mouse_ypos; 1075 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 1076 break; 1077 default: 1078 return EINVAL; 1079 } 1080 } 1081 1082 switch (mouse->operation) { 1083 case MOUSE_MODE: 1084 if (ISSIGVALID(mouse->u.mode.signal)) { 1085 scp->mouse_signal = mouse->u.mode.signal; 1086 scp->mouse_proc = p; 1087 scp->mouse_pid = p->p_pid; 1088 } 1089 else { 1090 scp->mouse_signal = 0; 1091 scp->mouse_proc = NULL; 1092 scp->mouse_pid = 0; 1093 } 1094 return 0; 1095 1096 case MOUSE_SHOW: 1097 if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) { 1098 scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); 1099 scp->mouse_oldpos = scp->mouse_pos; 1100 mark_all(scp); 1101 return 0; 1102 } 1103 else 1104 return EINVAL; 1105 break; 1106 1107 case MOUSE_HIDE: 1108 if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) { 1109 scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 1110 mark_all(scp); 1111 return 0; 1112 } 1113 else 1114 return EINVAL; 1115 break; 1116 1117 case MOUSE_MOVEABS: 1118 scp->mouse_xpos = mouse->u.data.x; 1119 scp->mouse_ypos = mouse->u.data.y; 1120 set_mouse_pos(scp); 1121 break; 1122 1123 case MOUSE_MOVEREL: 1124 scp->mouse_xpos += mouse->u.data.x; 1125 scp->mouse_ypos += mouse->u.data.y; 1126 set_mouse_pos(scp); 1127 break; 1128 1129 case MOUSE_GETINFO: 1130 mouse->u.data.x = scp->mouse_xpos; 1131 mouse->u.data.y = scp->mouse_ypos; 1132 mouse->u.data.z = 0; 1133 mouse->u.data.buttons = scp->mouse_buttons; 1134 return 0; 1135 1136 case MOUSE_ACTION: 1137 case MOUSE_MOTION_EVENT: 1138 /* this should maybe only be settable from /dev/consolectl SOS */ 1139 /* send out mouse event on /dev/sysmouse */ 1140 1141 mouse_status.dx += mouse->u.data.x; 1142 mouse_status.dy += mouse->u.data.y; 1143 mouse_status.dz += mouse->u.data.z; 1144 if (mouse->operation == MOUSE_ACTION) 1145 mouse_status.button = mouse->u.data.buttons; 1146 mouse_status.flags |= 1147 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 1148 MOUSE_POSCHANGED : 0) 1149 | (mouse_status.obutton ^ mouse_status.button); 1150 if (mouse_status.flags == 0) 1151 return 0; 1152 1153 if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) 1154 cur_console->status |= MOUSE_VISIBLE; 1155 1156 if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1157 u_char buf[MOUSE_SYS_PACKETSIZE]; 1158 int j; 1159 1160 /* the first five bytes are compatible with MouseSystems' */ 1161 buf[0] = MOUSE_MSC_SYNC 1162 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1163 j = imax(imin(mouse->u.data.x, 255), -256); 1164 buf[1] = j >> 1; 1165 buf[3] = j - buf[1]; 1166 j = -imax(imin(mouse->u.data.y, 255), -256); 1167 buf[2] = j >> 1; 1168 buf[4] = j - buf[2]; 1169 for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) 1170 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1171 if (mouse_level >= 1) { /* extended part */ 1172 j = imax(imin(mouse->u.data.z, 127), -128); 1173 buf[5] = (j >> 1) & 0x7f; 1174 buf[6] = (j - (j >> 1)) & 0x7f; 1175 /* buttons 4-10 */ 1176 buf[7] = (~mouse_status.button >> 3) & 0x7f; 1177 for (j = MOUSE_MSC_PACKETSIZE; 1178 j < MOUSE_SYS_PACKETSIZE; j++) 1179 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1180 } 1181 } 1182 1183 if (cur_console->mouse_signal) { 1184 cur_console->mouse_buttons = mouse->u.data.buttons; 1185 /* has controlling process died? */ 1186 if (cur_console->mouse_proc && 1187 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1188 cur_console->mouse_signal = 0; 1189 cur_console->mouse_proc = NULL; 1190 cur_console->mouse_pid = 0; 1191 } 1192 else 1193 psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1194 } 1195 else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) { 1196 /* process button presses */ 1197 if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 1198 ISTEXTSC(cur_console)) { 1199 cur_console->mouse_buttons = mouse->u.data.buttons; 1200 if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) 1201 mouse_cut_start(cur_console); 1202 else 1203 mouse_cut_end(cur_console); 1204 if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || 1205 cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) 1206 mouse_paste(cur_console); 1207 } 1208 } 1209 1210 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 1211 cur_console->mouse_xpos += mouse->u.data.x; 1212 cur_console->mouse_ypos += mouse->u.data.y; 1213 set_mouse_pos(cur_console); 1214 } 1215 1216 break; 1217 1218 case MOUSE_BUTTON_EVENT: 1219 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 1220 return EINVAL; 1221 if (mouse->u.event.value < 0) 1222 return EINVAL; 1223 1224 if (mouse->u.event.value > 0) { 1225 cur_console->mouse_buttons |= mouse->u.event.id; 1226 mouse_status.button |= mouse->u.event.id; 1227 } else { 1228 cur_console->mouse_buttons &= ~mouse->u.event.id; 1229 mouse_status.button &= ~mouse->u.event.id; 1230 } 1231 mouse_status.flags |= mouse_status.obutton ^ mouse_status.button; 1232 if (mouse_status.flags == 0) 1233 return 0; 1234 1235 if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) 1236 cur_console->status |= MOUSE_VISIBLE; 1237 1238 if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1239 u_char buf[8]; 1240 int i; 1241 1242 buf[0] = MOUSE_MSC_SYNC 1243 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1244 buf[7] = (~mouse_status.button >> 3) & 0x7f; 1245 buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 1246 for (i = 0; 1247 i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 1248 : MOUSE_MSC_PACKETSIZE); i++) 1249 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); 1250 } 1251 1252 if (cur_console->mouse_signal) { 1253 if (cur_console->mouse_proc && 1254 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1255 cur_console->mouse_signal = 0; 1256 cur_console->mouse_proc = NULL; 1257 cur_console->mouse_pid = 0; 1258 } 1259 else 1260 psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1261 break; 1262 } 1263 1264 if (!ISTEXTSC(cur_console) || (cut_buffer == NULL)) 1265 break; 1266 1267 switch (mouse->u.event.id) { 1268 case MOUSE_BUTTON1DOWN: 1269 switch (mouse->u.event.value % 4) { 1270 case 0: /* up */ 1271 mouse_cut_end(cur_console); 1272 break; 1273 case 1: 1274 mouse_cut_start(cur_console); 1275 break; 1276 case 2: 1277 mouse_cut_word(cur_console); 1278 break; 1279 case 3: 1280 mouse_cut_line(cur_console); 1281 break; 1282 } 1283 break; 1284 case MOUSE_BUTTON2DOWN: 1285 switch (mouse->u.event.value) { 1286 case 0: /* up */ 1287 break; 1288 default: 1289 mouse_paste(cur_console); 1290 break; 1291 } 1292 break; 1293 case MOUSE_BUTTON3DOWN: 1294 switch (mouse->u.event.value) { 1295 case 0: /* up */ 1296 if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) 1297 mouse_cut_end(cur_console); 1298 break; 1299 default: 1300 mouse_cut_extend(cur_console); 1301 break; 1302 } 1303 break; 1304 } 1305 break; 1306 1307 default: 1308 return EINVAL; 1309 } 1310 /* make screensaver happy */ 1311 scsplash_stick(FALSE); 1312 run_scrn_saver = FALSE; 1313 return 0; 1314 } 1315 1316 /* MOUSE_XXX: /dev/sysmouse ioctls */ 1317 case MOUSE_GETHWINFO: /* get device information */ 1318 { 1319 mousehw_t *hw = (mousehw_t *)data; 1320 1321 if (tp != MOUSE_TTY) 1322 return ENOTTY; 1323 hw->buttons = 10; /* XXX unknown */ 1324 hw->iftype = MOUSE_IF_SYSMOUSE; 1325 hw->type = MOUSE_MOUSE; 1326 hw->model = MOUSE_MODEL_GENERIC; 1327 hw->hwid = 0; 1328 return 0; 1329 } 1330 1331 case MOUSE_GETMODE: /* get protocol/mode */ 1332 { 1333 mousemode_t *mode = (mousemode_t *)data; 1334 1335 if (tp != MOUSE_TTY) 1336 return ENOTTY; 1337 mode->level = mouse_level; 1338 switch (mode->level) { 1339 case 0: 1340 /* at this level, sysmouse emulates MouseSystems protocol */ 1341 mode->protocol = MOUSE_PROTO_MSC; 1342 mode->rate = -1; /* unknown */ 1343 mode->resolution = -1; /* unknown */ 1344 mode->accelfactor = 0; /* disabled */ 1345 mode->packetsize = MOUSE_MSC_PACKETSIZE; 1346 mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 1347 mode->syncmask[1] = MOUSE_MSC_SYNC; 1348 break; 1349 1350 case 1: 1351 /* at this level, sysmouse uses its own protocol */ 1352 mode->protocol = MOUSE_PROTO_SYSMOUSE; 1353 mode->rate = -1; 1354 mode->resolution = -1; 1355 mode->accelfactor = 0; 1356 mode->packetsize = MOUSE_SYS_PACKETSIZE; 1357 mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 1358 mode->syncmask[1] = MOUSE_SYS_SYNC; 1359 break; 1360 } 1361 return 0; 1362 } 1363 1364 case MOUSE_SETMODE: /* set protocol/mode */ 1365 { 1366 mousemode_t *mode = (mousemode_t *)data; 1367 1368 if (tp != MOUSE_TTY) 1369 return ENOTTY; 1370 if ((mode->level < 0) || (mode->level > 1)) 1371 return EINVAL; 1372 mouse_level = mode->level; 1373 return 0; 1374 } 1375 1376 case MOUSE_GETLEVEL: /* get operation level */ 1377 if (tp != MOUSE_TTY) 1378 return ENOTTY; 1379 *(int *)data = mouse_level; 1380 return 0; 1381 1382 case MOUSE_SETLEVEL: /* set operation level */ 1383 if (tp != MOUSE_TTY) 1384 return ENOTTY; 1385 if ((*(int *)data < 0) || (*(int *)data > 1)) 1386 return EINVAL; 1387 mouse_level = *(int *)data; 1388 return 0; 1389 1390 case MOUSE_GETSTATUS: /* get accumulated mouse events */ 1391 if (tp != MOUSE_TTY) 1392 return ENOTTY; 1393 s = spltty(); 1394 *(mousestatus_t *)data = mouse_status; 1395 mouse_status.flags = 0; 1396 mouse_status.obutton = mouse_status.button; 1397 mouse_status.dx = 0; 1398 mouse_status.dy = 0; 1399 mouse_status.dz = 0; 1400 splx(s); 1401 return 0; 1402 1403#if notyet 1404 case MOUSE_GETVARS: /* get internal mouse variables */ 1405 case MOUSE_SETVARS: /* set internal mouse variables */ 1406 if (tp != MOUSE_TTY) 1407 return ENOTTY; 1408 return ENODEV; 1409#endif 1410 1411 case MOUSE_READSTATE: /* read status from the device */ 1412 case MOUSE_READDATA: /* read data from the device */ 1413 if (tp != MOUSE_TTY) 1414 return ENOTTY; 1415 return ENODEV; 1416 1417 case CONS_GETINFO: /* get current (virtual) console info */ 1418 { 1419 vid_info_t *ptr = (vid_info_t*)data; 1420 if (ptr->size == sizeof(struct vid_info)) { 1421 ptr->m_num = get_scr_num(); 1422 ptr->mv_col = scp->xpos; 1423 ptr->mv_row = scp->ypos; 1424 ptr->mv_csz = scp->xsize; 1425 ptr->mv_rsz = scp->ysize; 1426 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 1427 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 1428 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 1429 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 1430 ptr->mv_grfc.fore = 0; /* not supported */ 1431 ptr->mv_grfc.back = 0; /* not supported */ 1432 ptr->mv_ovscan = scp->border; 1433 ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 1434 return 0; 1435 } 1436 return EINVAL; 1437 } 1438 1439 case CONS_GETVERS: /* get version number */ 1440 *(int*)data = 0x200; /* version 2.0 */ 1441 return 0; 1442 1443 case CONS_IDLE: /* see if the screen has been idle */ 1444 /* 1445 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE, 1446 * the user process may have been writing something on the 1447 * screen and syscons is not aware of it. Declare the screen 1448 * is NOT idle if it is in one of these modes. But there is 1449 * an exception to it; if a screen saver is running in the 1450 * graphics mode in the current screen, we should say that the 1451 * screen has been idle. 1452 */ 1453 *(int *)data = scrn_idle 1454 && (!ISGRAPHSC(cur_console) 1455 || (cur_console->status & SAVER_RUNNING)); 1456 return 0; 1457 1458 case CONS_SAVERMODE: /* set saver mode */ 1459 switch(*(int *)data) { 1460 case CONS_USR_SAVER: 1461 /* if a LKM screen saver is running, stop it first. */ 1462 scsplash_stick(FALSE); 1463 saver_mode = *(int *)data; 1464 s = spltty(); 1465 if ((error = wait_scrn_saver_stop())) { 1466 splx(s); 1467 return error; 1468 } 1469 scp->status |= SAVER_RUNNING; 1470 scsplash_stick(TRUE); 1471 splx(s); 1472 break; 1473 case CONS_LKM_SAVER: 1474 s = spltty(); 1475 if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING)) 1476 scp->status &= ~SAVER_RUNNING; 1477 saver_mode = *(int *)data; 1478 splx(s); 1479 break; 1480 default: 1481 return EINVAL; 1482 } 1483 return 0; 1484 1485 case CONS_SAVERSTART: /* immediately start/stop the screen saver */ 1486 /* 1487 * Note that this ioctl does not guarantee the screen saver 1488 * actually starts or stops. It merely attempts to do so... 1489 */ 1490 s = spltty(); 1491 run_scrn_saver = (*(int *)data != 0); 1492 if (run_scrn_saver) 1493 scrn_time_stamp -= scrn_blank_time; 1494 splx(s); 1495 return 0; 1496 1497 case VT_SETMODE: /* set screen switcher mode */ 1498 { 1499 struct vt_mode *mode; 1500 1501 mode = (struct vt_mode *)data; 1502 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && 1503 ISSIGVALID(mode->frsig)) { 1504 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 1505 if (scp->smode.mode == VT_PROCESS) { 1506 scp->proc = p; 1507 scp->pid = scp->proc->p_pid; 1508 } 1509 return 0; 1510 } else 1511 return EINVAL; 1512 } 1513 1514 case VT_GETMODE: /* get screen switcher mode */ 1515 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 1516 return 0; 1517 1518 case VT_RELDISP: /* screen switcher ioctl */ 1519 switch(*(int *)data) { 1520 case VT_FALSE: /* user refuses to release screen, abort */ 1521 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1522 old_scp->status &= ~SWITCH_WAIT_REL; 1523 switch_in_progress = FALSE; 1524 return 0; 1525 } 1526 return EINVAL; 1527 1528 case VT_TRUE: /* user has released screen, go on */ 1529 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1530 scp->status &= ~SWITCH_WAIT_REL; 1531 exchange_scr(); 1532 if (new_scp->smode.mode == VT_PROCESS) { 1533 new_scp->status |= SWITCH_WAIT_ACQ; 1534 psignal(new_scp->proc, new_scp->smode.acqsig); 1535 } 1536 else 1537 switch_in_progress = FALSE; 1538 return 0; 1539 } 1540 return EINVAL; 1541 1542 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 1543 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 1544 scp->status &= ~SWITCH_WAIT_ACQ; 1545 switch_in_progress = FALSE; 1546 return 0; 1547 } 1548 return EINVAL; 1549 1550 default: 1551 return EINVAL; 1552 } 1553 /* NOT REACHED */ 1554 1555 case VT_OPENQRY: /* return free virtual console */ 1556 for (i = 0; i < MAXCONS; i++) { 1557 tp = VIRTUAL_TTY(i); 1558 if (!(tp->t_state & TS_ISOPEN)) { 1559 *(int *)data = i + 1; 1560 return 0; 1561 } 1562 } 1563 return EINVAL; 1564 1565 case VT_ACTIVATE: /* switch to screen *data */ 1566 return switch_scr(scp, *(int *)data - 1); 1567 1568 case VT_WAITACTIVE: /* wait for switch to occur */ 1569 if (*(int *)data > MAXCONS || *(int *)data < 0) 1570 return EINVAL; 1571 if (minor(dev) == *(int *)data - 1) 1572 return 0; 1573 if (*(int *)data == 0) { 1574 if (scp == cur_console) 1575 return 0; 1576 } 1577 else 1578 scp = console[*(int *)data - 1]; 1579 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1580 "waitvt", 0)) == ERESTART) ; 1581 return error; 1582 1583 case VT_GETACTIVE: 1584 *(int *)data = get_scr_num()+1; 1585 return 0; 1586 1587 case KDENABIO: /* allow io operations */ 1588 error = suser(p->p_ucred, &p->p_acflag); 1589 if (error != 0) 1590 return error; 1591 if (securelevel > 0) 1592 return EPERM; 1593 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 1594 return 0; 1595 1596 case KDDISABIO: /* disallow io operations (default) */ 1597 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 1598 return 0; 1599 1600 case KDSKBSTATE: /* set keyboard state (locks) */ 1601 if (*(int *)data & ~LOCK_KEY_MASK) 1602 return EINVAL; 1603 scp->status &= ~LOCK_KEY_MASK; 1604 scp->status |= *(int *)data; 1605 if (scp == cur_console) 1606 update_leds(scp->status); 1607 return 0; 1608 1609 case KDGKBSTATE: /* get keyboard state (locks) */ 1610 *(int *)data = scp->status & LOCK_KEY_MASK; 1611 return 0; 1612 1613 case KDSETRAD: /* set keyboard repeat & delay rates */ 1614 if (*(int *)data & ~0x7f) 1615 return EINVAL; 1616 if (sc_kbdc != NULL) 1617 set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data); 1618 return 0; 1619 1620 case KDSKBMODE: /* set keyboard mode */ 1621 switch (*(int *)data) { 1622 case K_RAW: /* switch to RAW scancode mode */ 1623 scp->status &= ~KBD_CODE_MODE; 1624 scp->status |= KBD_RAW_MODE; 1625 return 0; 1626 1627 case K_CODE: /* switch to CODE mode */ 1628 scp->status &= ~KBD_RAW_MODE; 1629 scp->status |= KBD_CODE_MODE; 1630 return 0; 1631 1632 case K_XLATE: /* switch to XLT ascii mode */ 1633 if (scp == cur_console && scp->status & KBD_RAW_MODE) 1634 shfts = ctls = alts = agrs = metas = accents = 0; 1635 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); 1636 return 0; 1637 default: 1638 return EINVAL; 1639 } 1640 /* NOT REACHED */ 1641 1642 case KDGKBMODE: /* get keyboard mode */ 1643 *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : 1644 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); 1645 return 0; 1646 1647 case KDMKTONE: /* sound the bell */ 1648 if (*(int*)data) 1649 do_bell(scp, (*(int*)data)&0xffff, 1650 (((*(int*)data)>>16)&0xffff)*hz/1000); 1651 else 1652 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1653 return 0; 1654 1655 case KIOCSOUND: /* make tone (*data) hz */ 1656 if (scp == cur_console) { 1657 if (*(int*)data) { 1658 int pitch = timer_freq / *(int*)data; 1659 1660 /* set command for counter 2, 2 byte write */ 1661 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1662 return EBUSY; 1663 1664 /* set pitch */ 1665 outb(TIMER_CNTR2, pitch); 1666 outb(TIMER_CNTR2, (pitch>>8)); 1667 1668 /* enable counter 2 output to speaker */ 1669 outb(IO_PPI, inb(IO_PPI) | 3); 1670 } 1671 else { 1672 /* disable counter 2 output to speaker */ 1673 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1674 release_timer2(); 1675 } 1676 } 1677 return 0; 1678 1679 case KDGKBTYPE: /* get keyboard type */ 1680 *(int *)data = 0; /* type not known (yet) */ 1681 return 0; 1682 1683 case KDSETLED: /* set keyboard LED status */ 1684 if (*(int *)data & ~LED_MASK) 1685 return EINVAL; 1686 scp->status &= ~LED_MASK; 1687 scp->status |= *(int *)data; 1688 if (scp == cur_console) 1689 update_leds(scp->status); 1690 return 0; 1691 1692 case KDGETLED: /* get keyboard LED status */ 1693 *(int *)data = scp->status & LED_MASK; 1694 return 0; 1695 1696 case GETFKEY: /* get functionkey string */ 1697 if (*(u_short*)data < n_fkey_tab) { 1698 fkeyarg_t *ptr = (fkeyarg_t*)data; 1699 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1700 fkey_tab[ptr->keynum].len); 1701 ptr->flen = fkey_tab[ptr->keynum].len; 1702 return 0; 1703 } 1704 else 1705 return EINVAL; 1706 1707 case SETFKEY: /* set functionkey string */ 1708 if (*(u_short*)data < n_fkey_tab) { 1709 fkeyarg_t *ptr = (fkeyarg_t*)data; 1710 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1711 min(ptr->flen, MAXFK)); 1712 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1713 return 0; 1714 } 1715 else 1716 return EINVAL; 1717 1718 case GIO_SCRNMAP: /* get output translation table */ 1719 bcopy(&scr_map, data, sizeof(scr_map)); 1720 return 0; 1721 1722 case PIO_SCRNMAP: /* set output translation table */ 1723 bcopy(data, &scr_map, sizeof(scr_map)); 1724 for (i=0; i<sizeof(scr_map); i++) 1725 scr_rmap[scr_map[i]] = i; 1726 return 0; 1727 1728 case GIO_KEYMAP: /* get keyboard translation table */ 1729 bcopy(&key_map, data, sizeof(key_map)); 1730 return 0; 1731 1732 case PIO_KEYMAP: /* set keyboard translation table */ 1733 accents = 0; 1734 bzero(&accent_map, sizeof(accent_map)); 1735 bcopy(data, &key_map, sizeof(key_map)); 1736 return 0; 1737 1738 case GIO_DEADKEYMAP: /* get accent key translation table */ 1739 bcopy(&accent_map, data, sizeof(accent_map)); 1740 return 0; 1741 1742 case PIO_DEADKEYMAP: /* set accent key translation table */ 1743 accents = 0; 1744 bcopy(data, &accent_map, sizeof(accent_map)); 1745 return 0; 1746 1747 case PIO_FONT8x8: /* set 8x8 dot font */ 1748 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1749 return ENXIO; 1750 bcopy(data, font_8, 8*256); 1751 fonts_loaded |= FONT_8; 1752 /* 1753 * FONT KLUDGE 1754 * Always use the font page #0. XXX 1755 * Don't load if the current font size is not 8x8. 1756 */ 1757 if (ISTEXTSC(cur_console) && (cur_console->font_size < 14)) 1758 copy_font(cur_console, LOAD, 8, font_8); 1759 return 0; 1760 1761 case GIO_FONT8x8: /* get 8x8 dot font */ 1762 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1763 return ENXIO; 1764 if (fonts_loaded & FONT_8) { 1765 bcopy(font_8, data, 8*256); 1766 return 0; 1767 } 1768 else 1769 return ENXIO; 1770 1771 case PIO_FONT8x14: /* set 8x14 dot font */ 1772 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1773 return ENXIO; 1774 bcopy(data, font_14, 14*256); 1775 fonts_loaded |= FONT_14; 1776 /* 1777 * FONT KLUDGE 1778 * Always use the font page #0. XXX 1779 * Don't load if the current font size is not 8x14. 1780 */ 1781 if (ISTEXTSC(cur_console) 1782 && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) 1783 copy_font(cur_console, LOAD, 14, font_14); 1784 return 0; 1785 1786 case GIO_FONT8x14: /* get 8x14 dot font */ 1787 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1788 return ENXIO; 1789 if (fonts_loaded & FONT_14) { 1790 bcopy(font_14, data, 14*256); 1791 return 0; 1792 } 1793 else 1794 return ENXIO; 1795 1796 case PIO_FONT8x16: /* set 8x16 dot font */ 1797 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1798 return ENXIO; 1799 bcopy(data, font_16, 16*256); 1800 fonts_loaded |= FONT_16; 1801 /* 1802 * FONT KLUDGE 1803 * Always use the font page #0. XXX 1804 * Don't load if the current font size is not 8x16. 1805 */ 1806 if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16)) 1807 copy_font(cur_console, LOAD, 16, font_16); 1808 return 0; 1809 1810 case GIO_FONT8x16: /* get 8x16 dot font */ 1811 if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) 1812 return ENXIO; 1813 if (fonts_loaded & FONT_16) { 1814 bcopy(font_16, data, 16*256); 1815 return 0; 1816 } 1817 else 1818 return ENXIO; 1819 default: 1820 break; 1821 } 1822 1823 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1824 if (error != ENOIOCTL) 1825 return(error); 1826 error = ttioctl(tp, cmd, data, flag); 1827 if (error != ENOIOCTL) 1828 return(error); 1829 return(ENOTTY); 1830} 1831 1832static void 1833scstart(struct tty *tp) 1834{ 1835 struct clist *rbp; 1836 int s, len; 1837 u_char buf[PCBURST]; 1838 scr_stat *scp = sc_get_scr_stat(tp->t_dev); 1839 1840 if (scp->status & SLKED || blink_in_progress) 1841 return; /* XXX who repeats the call when the above flags are cleared? */ 1842 s = spltty(); 1843 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1844 tp->t_state |= TS_BUSY; 1845 rbp = &tp->t_outq; 1846 while (rbp->c_cc) { 1847 len = q_to_b(rbp, buf, PCBURST); 1848 splx(s); 1849 ansi_put(scp, buf, len); 1850 s = spltty(); 1851 } 1852 tp->t_state &= ~TS_BUSY; 1853 ttwwakeup(tp); 1854 } 1855 splx(s); 1856} 1857 1858static void 1859scmousestart(struct tty *tp) 1860{ 1861 struct clist *rbp; 1862 int s; 1863 u_char buf[PCBURST]; 1864 1865 s = spltty(); 1866 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1867 tp->t_state |= TS_BUSY; 1868 rbp = &tp->t_outq; 1869 while (rbp->c_cc) { 1870 q_to_b(rbp, buf, PCBURST); 1871 } 1872 tp->t_state &= ~TS_BUSY; 1873 ttwwakeup(tp); 1874 } 1875 splx(s); 1876} 1877 1878void 1879sccnprobe(struct consdev *cp) 1880{ 1881 struct isa_device *dvp; 1882 1883 /* 1884 * Take control if we are the highest priority enabled display device. 1885 */ 1886 dvp = find_display(); 1887 if (dvp == NULL || dvp->id_driver != &scdriver) { 1888 cp->cn_pri = CN_DEAD; 1889 return; 1890 } 1891 1892 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { 1893 cp->cn_pri = CN_DEAD; 1894 return; 1895 } 1896 1897 /* initialize required fields */ 1898 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 1899 cp->cn_pri = CN_INTERNAL; 1900 1901 sc_kbdc = kbdc_open(sc_port); 1902} 1903 1904void 1905sccninit(struct consdev *cp) 1906{ 1907 scinit(); 1908} 1909 1910void 1911sccnputc(dev_t dev, int c) 1912{ 1913 u_char buf[1]; 1914 int s; 1915 scr_stat *scp = console[0]; 1916 term_stat save = scp->term; 1917 1918 scp->term = kernel_console; 1919 current_default = &kernel_default; 1920 if (scp == cur_console && !ISGRAPHSC(scp)) 1921 remove_cursor_image(scp); 1922 buf[0] = c; 1923 ansi_put(scp, buf, 1); 1924 kernel_console = scp->term; 1925 current_default = &user_default; 1926 scp->term = save; 1927 1928 s = spltty(); /* block scintr and scrn_timer */ 1929 sccnupdate(scp); 1930 splx(s); 1931} 1932 1933int 1934sccngetc(dev_t dev) 1935{ 1936 int s = spltty(); /* block scintr and scrn_timer while we poll */ 1937 int c; 1938 1939 /* 1940 * Stop the screen saver and update the screen if necessary. 1941 * What if we have been running in the screen saver code... XXX 1942 */ 1943 scsplash_stick(FALSE); 1944 run_scrn_saver = FALSE; 1945 sccnupdate(cur_console); 1946 1947 c = scgetc(SCGETC_CN); 1948 splx(s); 1949 return(c); 1950} 1951 1952int 1953sccncheckc(dev_t dev) 1954{ 1955 int s = spltty(); /* block scintr and scrn_timer while we poll */ 1956 int c; 1957 1958 scsplash_stick(FALSE); 1959 run_scrn_saver = FALSE; 1960 sccnupdate(cur_console); 1961 1962 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); 1963 splx(s); 1964 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ 1965} 1966 1967static void 1968sccnupdate(scr_stat *scp) 1969{ 1970 /* this is a cut-down version of scrn_timer()... */ 1971 1972 if (font_loading_in_progress) 1973 return; 1974 1975 if (panicstr || shutdown_in_progress) { 1976 scsplash_stick(FALSE); 1977 run_scrn_saver = FALSE; 1978 } else if (scp != cur_console) { 1979 return; 1980 } 1981 1982 if (!run_scrn_saver) 1983 scrn_idle = FALSE; 1984 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 1985 if (scp->status & SAVER_RUNNING) 1986 stop_scrn_saver(current_saver); 1987 1988 if (scp != cur_console || blink_in_progress || switch_in_progress) 1989 return; 1990 1991 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 1992 scrn_update(scp, TRUE); 1993} 1994 1995scr_stat 1996*sc_get_scr_stat(dev_t dev) 1997{ 1998 int unit = minor(dev); 1999 2000 if (unit == SC_CONSOLE) 2001 return console[0]; 2002 if (unit >= MAXCONS || unit < 0) 2003 return(NULL); 2004 return console[unit]; 2005} 2006 2007static int 2008get_scr_num() 2009{ 2010 int i = 0; 2011 2012 while ((i < MAXCONS) && (cur_console != console[i])) 2013 i++; 2014 return i < MAXCONS ? i : 0; 2015} 2016 2017static void 2018scrn_timer(void *arg) 2019{ 2020 struct timeval tv; 2021 scr_stat *scp; 2022 int s; 2023 2024 /* don't do anything when we are touching font */ 2025 if (font_loading_in_progress) { 2026 if (arg) 2027 timeout(scrn_timer, (void *)TRUE, hz / 10); 2028 return; 2029 } 2030 s = spltty(); 2031 2032 /* 2033 * With release 2.1 of the Xaccel server, the keyboard is left 2034 * hanging pretty often. Apparently an interrupt from the 2035 * keyboard is lost, and I don't know why (yet). 2036 * This ugly hack calls scintr if input is ready for the keyboard 2037 * and conveniently hides the problem. XXX 2038 */ 2039 /* Try removing anything stuck in the keyboard controller; whether 2040 * it's a keyboard scan code or mouse data. `scintr()' doesn't 2041 * read the mouse data directly, but `kbdio' routines will, as a 2042 * side effect. 2043 */ 2044 if (kbdc_lock(sc_kbdc, TRUE)) { 2045 /* 2046 * We have seen the lock flag is not set. Let's reset the flag early; 2047 * otherwise `update_led()' failes which may want the lock 2048 * during `scintr()'. 2049 */ 2050 kbdc_lock(sc_kbdc, FALSE); 2051 if (kbdc_data_ready(sc_kbdc)) 2052 scintr(0); 2053 } 2054 2055 scp = cur_console; 2056 2057 /* should we stop the screen saver? */ 2058 getmicrouptime(&tv); 2059 if (panicstr || shutdown_in_progress) { 2060 scsplash_stick(FALSE); 2061 run_scrn_saver = FALSE; 2062 } 2063 if (run_scrn_saver) { 2064 scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time); 2065 } else { 2066 scrn_time_stamp = tv.tv_sec; 2067 scrn_idle = FALSE; 2068 if (scrn_blank_time > 0) 2069 run_scrn_saver = TRUE; 2070 } 2071 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 2072 if (scp->status & SAVER_RUNNING) 2073 stop_scrn_saver(current_saver); 2074 2075 /* should we just return ? */ 2076 if (blink_in_progress || switch_in_progress) { 2077 if (arg) 2078 timeout(scrn_timer, (void *)TRUE, hz / 10); 2079 splx(s); 2080 return; 2081 } 2082 2083 /* Update the screen */ 2084 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 2085 scrn_update(scp, TRUE); 2086 2087 /* should we activate the screen saver? */ 2088 if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) 2089 if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING)) 2090 scrn_saver(current_saver, TRUE); 2091 2092 if (arg) 2093 timeout(scrn_timer, (void *)TRUE, hz / 25); 2094 splx(s); 2095} 2096 2097static void 2098scrn_update(scr_stat *scp, int show_cursor) 2099{ 2100 /* update screen image */ 2101 if (scp->start <= scp->end) 2102 sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0); 2103 2104 /* we are not to show the cursor and the mouse pointer... */ 2105 if (!show_cursor) { 2106 scp->end = 0; 2107 scp->start = scp->xsize*scp->ysize - 1; 2108 return; 2109 } 2110 2111 /* update "pseudo" mouse pointer image */ 2112 if (scp->status & MOUSE_VISIBLE) { 2113 /* did mouse move since last time ? */ 2114 if (scp->status & MOUSE_MOVED) { 2115 /* do we need to remove old mouse pointer image ? */ 2116 if (scp->mouse_cut_start != NULL || 2117 (scp->mouse_pos-scp->scr_buf) <= scp->start || 2118 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) { 2119 remove_mouse_image(scp); 2120 } 2121 scp->status &= ~MOUSE_MOVED; 2122 draw_mouse_image(scp); 2123 } 2124 else { 2125 /* mouse didn't move, has it been overwritten ? */ 2126 if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start && 2127 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 2128 draw_mouse_image(scp); 2129 } 2130 } 2131 } 2132 2133 /* update cursor image */ 2134 if (scp->status & CURSOR_ENABLED) { 2135 /* did cursor move since last time ? */ 2136 if (scp->cursor_pos != scp->cursor_oldpos) { 2137 /* do we need to remove old cursor image ? */ 2138 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 2139 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 2140 remove_cursor_image(scp); 2141 } 2142 scp->cursor_oldpos = scp->cursor_pos; 2143 draw_cursor_image(scp); 2144 } 2145 else { 2146 /* cursor didn't move, has it been overwritten ? */ 2147 if (scp->cursor_pos - scp->scr_buf >= scp->start && 2148 scp->cursor_pos - scp->scr_buf <= scp->end) { 2149 draw_cursor_image(scp); 2150 } else { 2151 /* if its a blinking cursor, we may have to update it */ 2152 if (sc_flags & BLINK_CURSOR) 2153 draw_cursor_image(scp); 2154 } 2155 } 2156 blinkrate++; 2157 } 2158 2159 if (scp->mouse_cut_start != NULL) 2160 draw_cutmarking(scp); 2161 2162 scp->end = 0; 2163 scp->start = scp->xsize*scp->ysize - 1; 2164} 2165 2166int 2167add_scrn_saver(void (*this_saver)(int)) 2168{ 2169#ifdef SC_SPLASH_SCREEN 2170 if (current_saver == scsplash) { 2171 scsplash_stick(FALSE); 2172 stop_scrn_saver(scsplash); 2173 } 2174#endif 2175 2176 if (current_saver != default_saver) 2177 return EBUSY; 2178 run_scrn_saver = FALSE; 2179 saver_mode = CONS_LKM_SAVER; 2180 current_saver = this_saver; 2181 return 0; 2182} 2183 2184int 2185remove_scrn_saver(void (*this_saver)(int)) 2186{ 2187 if (current_saver != this_saver) 2188 return EINVAL; 2189 2190 /* 2191 * In order to prevent `current_saver' from being called by 2192 * the timeout routine `scrn_timer()' while we manipulate 2193 * the saver list, we shall set `current_saver' to `none_saver' 2194 * before stopping the current saver, rather than blocking by `splXX()'. 2195 */ 2196 current_saver = none_saver; 2197 if (scrn_blanked > 0) 2198 stop_scrn_saver(this_saver); 2199 2200 if (scrn_blanked > 0) 2201 return EBUSY; /* XXX */ 2202 2203 current_saver = default_saver; 2204 return 0; 2205} 2206 2207static void 2208scrn_saver(void (*saver)(int), int blank) 2209{ 2210 static int busy = FALSE; 2211 2212 if (busy) 2213 return; 2214 busy = TRUE; 2215 (*saver)(blank); 2216 busy = FALSE; 2217} 2218 2219static void 2220stop_scrn_saver(void (*saver)(int)) 2221{ 2222 scrn_saver(saver, FALSE); 2223 run_scrn_saver = FALSE; 2224 /* the screen saver may have chosen not to stop after all... */ 2225 if (scrn_blanked > 0) 2226 return; 2227 2228 mark_all(cur_console); 2229 if (delayed_next_scr) 2230 switch_scr(cur_console, delayed_next_scr - 1); 2231 wakeup((caddr_t)&scrn_blanked); 2232} 2233 2234static int 2235wait_scrn_saver_stop(void) 2236{ 2237 int error = 0; 2238 2239 while (scrn_blanked > 0) { 2240 run_scrn_saver = FALSE; 2241 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); 2242 run_scrn_saver = FALSE; 2243 if (error != ERESTART) 2244 break; 2245 } 2246 return error; 2247} 2248 2249void 2250sc_clear_screen(scr_stat *scp) 2251{ 2252 move_crsr(scp, 0, 0); 2253 scp->cursor_oldpos = scp->cursor_pos; 2254 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2255 scp->xsize * scp->ysize); 2256 mark_all(scp); 2257 remove_cutmarking(scp); 2258} 2259 2260static int 2261switch_scr(scr_stat *scp, u_int next_scr) 2262{ 2263 /* delay switch if actively updating screen */ 2264 if (scrn_blanked > 0 || write_in_progress || blink_in_progress) { 2265 scsplash_stick(FALSE); 2266 run_scrn_saver = FALSE; 2267 delayed_next_scr = next_scr+1; 2268 return 0; 2269 } 2270 2271 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 2272 switch_in_progress = FALSE; 2273 2274 if (next_scr >= MAXCONS || switch_in_progress || 2275 (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { 2276 do_bell(scp, BELL_PITCH, BELL_DURATION); 2277 return EINVAL; 2278 } 2279 2280 /* is the wanted virtual console open ? */ 2281 if (next_scr) { 2282 struct tty *tp = VIRTUAL_TTY(next_scr); 2283 if (!(tp->t_state & TS_ISOPEN)) { 2284 do_bell(scp, BELL_PITCH, BELL_DURATION); 2285 return EINVAL; 2286 } 2287 } 2288 2289 switch_in_progress = TRUE; 2290 old_scp = cur_console; 2291 new_scp = console[next_scr]; 2292 wakeup((caddr_t)&new_scp->smode); 2293 if (new_scp == old_scp) { 2294 switch_in_progress = FALSE; 2295 delayed_next_scr = FALSE; 2296 return 0; 2297 } 2298 2299 /* has controlling process died? */ 2300 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 2301 old_scp->smode.mode = VT_AUTO; 2302 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 2303 new_scp->smode.mode = VT_AUTO; 2304 2305 /* check the modes and switch appropriately */ 2306 if (old_scp->smode.mode == VT_PROCESS) { 2307 old_scp->status |= SWITCH_WAIT_REL; 2308 psignal(old_scp->proc, old_scp->smode.relsig); 2309 } 2310 else { 2311 exchange_scr(); 2312 if (new_scp->smode.mode == VT_PROCESS) { 2313 new_scp->status |= SWITCH_WAIT_ACQ; 2314 psignal(new_scp->proc, new_scp->smode.acqsig); 2315 } 2316 else 2317 switch_in_progress = FALSE; 2318 } 2319 return 0; 2320} 2321 2322static void 2323exchange_scr(void) 2324{ 2325 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 2326 cur_console = new_scp; 2327 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) 2328 set_mode(new_scp); 2329 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 2330 if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) 2331 set_destructive_cursor(new_scp); 2332 if (ISGRAPHSC(old_scp)) 2333 load_palette(new_scp, palette); 2334 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || 2335 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) 2336 shfts = ctls = alts = agrs = metas = accents = 0; 2337 set_border(new_scp, new_scp->border); 2338 update_leds(new_scp->status); 2339 delayed_next_scr = FALSE; 2340 mark_all(new_scp); 2341} 2342 2343static void 2344scan_esc(scr_stat *scp, u_char c) 2345{ 2346 static u_char ansi_col[16] = 2347 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2348 int i, n; 2349 u_short *src, *dst, count; 2350 2351 if (scp->term.esc == 1) { /* seen ESC */ 2352 switch (c) { 2353 2354 case '7': /* Save cursor position */ 2355 scp->saved_xpos = scp->xpos; 2356 scp->saved_ypos = scp->ypos; 2357 break; 2358 2359 case '8': /* Restore saved cursor position */ 2360 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2361 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2362 break; 2363 2364 case '[': /* Start ESC [ sequence */ 2365 scp->term.esc = 2; 2366 scp->term.last_param = -1; 2367 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2368 scp->term.param[i] = 1; 2369 scp->term.num_param = 0; 2370 return; 2371 2372 case 'M': /* Move cursor up 1 line, scroll if at top */ 2373 if (scp->ypos > 0) 2374 move_crsr(scp, scp->xpos, scp->ypos - 1); 2375 else { 2376 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 2377 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 2378 fillw(scp->term.cur_color | scr_map[0x20], 2379 scp->scr_buf, scp->xsize); 2380 mark_all(scp); 2381 } 2382 break; 2383#if notyet 2384 case 'Q': 2385 scp->term.esc = 4; 2386 return; 2387#endif 2388 case 'c': /* Clear screen & home */ 2389 sc_clear_screen(scp); 2390 break; 2391 2392 case '(': /* iso-2022: designate 94 character set to G0 */ 2393 scp->term.esc = 5; 2394 return; 2395 } 2396 } 2397 else if (scp->term.esc == 2) { /* seen ESC [ */ 2398 if (c >= '0' && c <= '9') { 2399 if (scp->term.num_param < MAX_ESC_PAR) { 2400 if (scp->term.last_param != scp->term.num_param) { 2401 scp->term.last_param = scp->term.num_param; 2402 scp->term.param[scp->term.num_param] = 0; 2403 } 2404 else 2405 scp->term.param[scp->term.num_param] *= 10; 2406 scp->term.param[scp->term.num_param] += c - '0'; 2407 return; 2408 } 2409 } 2410 scp->term.num_param = scp->term.last_param + 1; 2411 switch (c) { 2412 2413 case ';': 2414 if (scp->term.num_param < MAX_ESC_PAR) 2415 return; 2416 break; 2417 2418 case '=': 2419 scp->term.esc = 3; 2420 scp->term.last_param = -1; 2421 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2422 scp->term.param[i] = 1; 2423 scp->term.num_param = 0; 2424 return; 2425 2426 case 'A': /* up 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 'B': /* down n rows */ 2432 n = scp->term.param[0]; if (n < 1) n = 1; 2433 move_crsr(scp, scp->xpos, scp->ypos + n); 2434 break; 2435 2436 case 'C': /* right 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 'D': /* left n columns */ 2442 n = scp->term.param[0]; if (n < 1) n = 1; 2443 move_crsr(scp, scp->xpos - n, scp->ypos); 2444 break; 2445 2446 case 'E': /* cursor to start of line n lines down */ 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 to start of line n lines up */ 2452 n = scp->term.param[0]; if (n < 1) n = 1; 2453 move_crsr(scp, 0, scp->ypos - n); 2454 break; 2455 2456 case 'f': /* Cursor move */ 2457 case 'H': 2458 if (scp->term.num_param == 0) 2459 move_crsr(scp, 0, 0); 2460 else if (scp->term.num_param == 2) 2461 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2462 break; 2463 2464 case 'J': /* Clear all or part of display */ 2465 if (scp->term.num_param == 0) 2466 n = 0; 2467 else 2468 n = scp->term.param[0]; 2469 switch (n) { 2470 case 0: /* clear form cursor to end of display */ 2471 fillw(scp->term.cur_color | scr_map[0x20], 2472 scp->cursor_pos, 2473 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2474 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2475 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2476 remove_cutmarking(scp); 2477 break; 2478 case 1: /* clear from beginning of display to cursor */ 2479 fillw(scp->term.cur_color | scr_map[0x20], 2480 scp->scr_buf, 2481 scp->cursor_pos - scp->scr_buf); 2482 mark_for_update(scp, 0); 2483 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2484 remove_cutmarking(scp); 2485 break; 2486 case 2: /* clear entire display */ 2487 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2488 scp->xsize * scp->ysize); 2489 mark_all(scp); 2490 remove_cutmarking(scp); 2491 break; 2492 } 2493 break; 2494 2495 case 'K': /* Clear all or part of line */ 2496 if (scp->term.num_param == 0) 2497 n = 0; 2498 else 2499 n = scp->term.param[0]; 2500 switch (n) { 2501 case 0: /* clear form cursor to end of line */ 2502 fillw(scp->term.cur_color | scr_map[0x20], 2503 scp->cursor_pos, 2504 scp->xsize - scp->xpos); 2505 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2506 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2507 scp->xsize - 1 - scp->xpos); 2508 break; 2509 case 1: /* clear from beginning of line to cursor */ 2510 fillw(scp->term.cur_color | scr_map[0x20], 2511 scp->cursor_pos - scp->xpos, 2512 scp->xpos + 1); 2513 mark_for_update(scp, scp->ypos * scp->xsize); 2514 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2515 break; 2516 case 2: /* clear entire line */ 2517 fillw(scp->term.cur_color | scr_map[0x20], 2518 scp->cursor_pos - scp->xpos, 2519 scp->xsize); 2520 mark_for_update(scp, scp->ypos * scp->xsize); 2521 mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); 2522 break; 2523 } 2524 break; 2525 2526 case 'L': /* Insert n lines */ 2527 n = scp->term.param[0]; if (n < 1) n = 1; 2528 if (n > scp->ysize - scp->ypos) 2529 n = scp->ysize - scp->ypos; 2530 src = scp->scr_buf + scp->ypos * scp->xsize; 2531 dst = src + n * scp->xsize; 2532 count = scp->ysize - (scp->ypos + n); 2533 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2534 fillw(scp->term.cur_color | scr_map[0x20], src, 2535 n * scp->xsize); 2536 mark_for_update(scp, scp->ypos * scp->xsize); 2537 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2538 break; 2539 2540 case 'M': /* Delete n lines */ 2541 n = scp->term.param[0]; if (n < 1) n = 1; 2542 if (n > scp->ysize - scp->ypos) 2543 n = scp->ysize - scp->ypos; 2544 dst = scp->scr_buf + scp->ypos * scp->xsize; 2545 src = dst + n * scp->xsize; 2546 count = scp->ysize - (scp->ypos + n); 2547 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2548 src = dst + count * scp->xsize; 2549 fillw(scp->term.cur_color | scr_map[0x20], src, 2550 n * scp->xsize); 2551 mark_for_update(scp, scp->ypos * scp->xsize); 2552 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2553 break; 2554 2555 case 'P': /* Delete n chars */ 2556 n = scp->term.param[0]; if (n < 1) n = 1; 2557 if (n > scp->xsize - scp->xpos) 2558 n = scp->xsize - scp->xpos; 2559 dst = scp->cursor_pos; 2560 src = dst + n; 2561 count = scp->xsize - (scp->xpos + n); 2562 bcopy(src, dst, count * sizeof(u_short)); 2563 src = dst + count; 2564 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2565 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2566 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2567 break; 2568 2569 case '@': /* Insert n chars */ 2570 n = scp->term.param[0]; if (n < 1) n = 1; 2571 if (n > scp->xsize - scp->xpos) 2572 n = scp->xsize - scp->xpos; 2573 src = scp->cursor_pos; 2574 dst = src + n; 2575 count = scp->xsize - (scp->xpos + n); 2576 bcopy(src, dst, count * sizeof(u_short)); 2577 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2578 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2579 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2580 break; 2581 2582 case 'S': /* scroll up n lines */ 2583 n = scp->term.param[0]; if (n < 1) n = 1; 2584 if (n > scp->ysize) 2585 n = scp->ysize; 2586 bcopy(scp->scr_buf + (scp->xsize * n), 2587 scp->scr_buf, 2588 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2589 fillw(scp->term.cur_color | scr_map[0x20], 2590 scp->scr_buf + scp->xsize * (scp->ysize - n), 2591 scp->xsize * n); 2592 mark_all(scp); 2593 break; 2594 2595 case 'T': /* scroll down n lines */ 2596 n = scp->term.param[0]; if (n < 1) n = 1; 2597 if (n > scp->ysize) 2598 n = scp->ysize; 2599 bcopy(scp->scr_buf, 2600 scp->scr_buf + (scp->xsize * n), 2601 scp->xsize * (scp->ysize - n) * 2602 sizeof(u_short)); 2603 fillw(scp->term.cur_color | scr_map[0x20], 2604 scp->scr_buf, scp->xsize * n); 2605 mark_all(scp); 2606 break; 2607 2608 case 'X': /* erase n characters in line */ 2609 n = scp->term.param[0]; if (n < 1) n = 1; 2610 if (n > scp->xsize - scp->xpos) 2611 n = scp->xsize - scp->xpos; 2612 fillw(scp->term.cur_color | scr_map[0x20], 2613 scp->cursor_pos, n); 2614 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2615 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1); 2616 break; 2617 2618 case 'Z': /* move n tabs backwards */ 2619 n = scp->term.param[0]; if (n < 1) n = 1; 2620 if ((i = scp->xpos & 0xf8) == scp->xpos) 2621 i -= 8*n; 2622 else 2623 i -= 8*(n-1); 2624 if (i < 0) 2625 i = 0; 2626 move_crsr(scp, i, scp->ypos); 2627 break; 2628 2629 case '`': /* move cursor to column n */ 2630 n = scp->term.param[0]; if (n < 1) n = 1; 2631 move_crsr(scp, n - 1, scp->ypos); 2632 break; 2633 2634 case 'a': /* move cursor n columns to the right */ 2635 n = scp->term.param[0]; if (n < 1) n = 1; 2636 move_crsr(scp, scp->xpos + n, scp->ypos); 2637 break; 2638 2639 case 'd': /* move cursor to row n */ 2640 n = scp->term.param[0]; if (n < 1) n = 1; 2641 move_crsr(scp, scp->xpos, n - 1); 2642 break; 2643 2644 case 'e': /* move cursor n rows down */ 2645 n = scp->term.param[0]; if (n < 1) n = 1; 2646 move_crsr(scp, scp->xpos, scp->ypos + n); 2647 break; 2648 2649 case 'm': /* change attribute */ 2650 if (scp->term.num_param == 0) { 2651 scp->term.attr_mask = NORMAL_ATTR; 2652 scp->term.cur_attr = 2653 scp->term.cur_color = scp->term.std_color; 2654 break; 2655 } 2656 for (i = 0; i < scp->term.num_param; i++) { 2657 switch (n = scp->term.param[i]) { 2658 case 0: /* back to normal */ 2659 scp->term.attr_mask = NORMAL_ATTR; 2660 scp->term.cur_attr = 2661 scp->term.cur_color = scp->term.std_color; 2662 break; 2663 case 1: /* bold */ 2664 scp->term.attr_mask |= BOLD_ATTR; 2665 scp->term.cur_attr = mask2attr(&scp->term); 2666 break; 2667 case 4: /* underline */ 2668 scp->term.attr_mask |= UNDERLINE_ATTR; 2669 scp->term.cur_attr = mask2attr(&scp->term); 2670 break; 2671 case 5: /* blink */ 2672 scp->term.attr_mask |= BLINK_ATTR; 2673 scp->term.cur_attr = mask2attr(&scp->term); 2674 break; 2675 case 7: /* reverse video */ 2676 scp->term.attr_mask |= REVERSE_ATTR; 2677 scp->term.cur_attr = mask2attr(&scp->term); 2678 break; 2679 case 30: case 31: /* set fg color */ 2680 case 32: case 33: case 34: 2681 case 35: case 36: case 37: 2682 scp->term.attr_mask |= FOREGROUND_CHANGED; 2683 scp->term.cur_color = 2684 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2685 scp->term.cur_attr = mask2attr(&scp->term); 2686 break; 2687 case 40: case 41: /* set bg color */ 2688 case 42: case 43: case 44: 2689 case 45: case 46: case 47: 2690 scp->term.attr_mask |= BACKGROUND_CHANGED; 2691 scp->term.cur_color = 2692 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2693 scp->term.cur_attr = mask2attr(&scp->term); 2694 break; 2695 } 2696 } 2697 break; 2698 2699 case 's': /* Save cursor position */ 2700 scp->saved_xpos = scp->xpos; 2701 scp->saved_ypos = scp->ypos; 2702 break; 2703 2704 case 'u': /* Restore saved cursor position */ 2705 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2706 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2707 break; 2708 2709 case 'x': 2710 if (scp->term.num_param == 0) 2711 n = 0; 2712 else 2713 n = scp->term.param[0]; 2714 switch (n) { 2715 case 0: /* reset attributes */ 2716 scp->term.attr_mask = NORMAL_ATTR; 2717 scp->term.cur_attr = 2718 scp->term.cur_color = scp->term.std_color = 2719 current_default->std_color; 2720 scp->term.rev_color = current_default->rev_color; 2721 break; 2722 case 1: /* set ansi background */ 2723 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2724 scp->term.cur_color = scp->term.std_color = 2725 (scp->term.std_color & 0x0F00) | 2726 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2727 scp->term.cur_attr = mask2attr(&scp->term); 2728 break; 2729 case 2: /* set ansi foreground */ 2730 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2731 scp->term.cur_color = scp->term.std_color = 2732 (scp->term.std_color & 0xF000) | 2733 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2734 scp->term.cur_attr = mask2attr(&scp->term); 2735 break; 2736 case 3: /* set ansi attribute directly */ 2737 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2738 scp->term.cur_color = scp->term.std_color = 2739 (scp->term.param[1]&0xFF)<<8; 2740 scp->term.cur_attr = mask2attr(&scp->term); 2741 break; 2742 case 5: /* set ansi reverse video background */ 2743 scp->term.rev_color = 2744 (scp->term.rev_color & 0x0F00) | 2745 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2746 scp->term.cur_attr = mask2attr(&scp->term); 2747 break; 2748 case 6: /* set ansi reverse video foreground */ 2749 scp->term.rev_color = 2750 (scp->term.rev_color & 0xF000) | 2751 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2752 scp->term.cur_attr = mask2attr(&scp->term); 2753 break; 2754 case 7: /* set ansi reverse video directly */ 2755 scp->term.rev_color = 2756 (scp->term.param[1]&0xFF)<<8; 2757 scp->term.cur_attr = mask2attr(&scp->term); 2758 break; 2759 } 2760 break; 2761 2762 case 'z': /* switch to (virtual) console n */ 2763 if (scp->term.num_param == 1) 2764 switch_scr(scp, scp->term.param[0]); 2765 break; 2766 } 2767 } 2768 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2769 if (c >= '0' && c <= '9') { 2770 if (scp->term.num_param < MAX_ESC_PAR) { 2771 if (scp->term.last_param != scp->term.num_param) { 2772 scp->term.last_param = scp->term.num_param; 2773 scp->term.param[scp->term.num_param] = 0; 2774 } 2775 else 2776 scp->term.param[scp->term.num_param] *= 10; 2777 scp->term.param[scp->term.num_param] += c - '0'; 2778 return; 2779 } 2780 } 2781 scp->term.num_param = scp->term.last_param + 1; 2782 switch (c) { 2783 2784 case ';': 2785 if (scp->term.num_param < MAX_ESC_PAR) 2786 return; 2787 break; 2788 2789 case 'A': /* set display border color */ 2790 if (scp->term.num_param == 1) { 2791 scp->border=scp->term.param[0] & 0xff; 2792 if (scp == cur_console) 2793 set_border(cur_console, scp->border); 2794 } 2795 break; 2796 2797 case 'B': /* set bell pitch and duration */ 2798 if (scp->term.num_param == 2) { 2799 scp->bell_pitch = scp->term.param[0]; 2800 scp->bell_duration = scp->term.param[1]; 2801 } 2802 break; 2803 2804 case 'C': /* set cursor type & shape */ 2805 if (scp->term.num_param == 1) { 2806 if (scp->term.param[0] & 0x01) 2807 sc_flags |= BLINK_CURSOR; 2808 else 2809 sc_flags &= ~BLINK_CURSOR; 2810 if ((scp->term.param[0] & 0x02) 2811 && ISFONTAVAIL(get_adapter(scp)->va_flags)) 2812 sc_flags |= CHAR_CURSOR; 2813 else 2814 sc_flags &= ~CHAR_CURSOR; 2815 } 2816 else if (scp->term.num_param == 2) { 2817 scp->cursor_start = scp->term.param[0] & 0x1F; 2818 scp->cursor_end = scp->term.param[1] & 0x1F; 2819 } 2820 /* 2821 * The cursor shape is global property; all virtual consoles 2822 * are affected. Update the cursor in the current console... 2823 */ 2824 if (!ISGRAPHSC(cur_console)) { 2825 i = spltty(); 2826 remove_cursor_image(cur_console); 2827 if (sc_flags & CHAR_CURSOR) 2828 set_destructive_cursor(cur_console); 2829 draw_cursor_image(cur_console); 2830 splx(i); 2831 } 2832 break; 2833 2834 case 'F': /* set ansi foreground */ 2835 if (scp->term.num_param == 1) { 2836 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2837 scp->term.cur_color = scp->term.std_color = 2838 (scp->term.std_color & 0xF000) 2839 | ((scp->term.param[0] & 0x0F) << 8); 2840 scp->term.cur_attr = mask2attr(&scp->term); 2841 } 2842 break; 2843 2844 case 'G': /* set ansi background */ 2845 if (scp->term.num_param == 1) { 2846 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2847 scp->term.cur_color = scp->term.std_color = 2848 (scp->term.std_color & 0x0F00) 2849 | ((scp->term.param[0] & 0x0F) << 12); 2850 scp->term.cur_attr = mask2attr(&scp->term); 2851 } 2852 break; 2853 2854 case 'H': /* set ansi reverse video foreground */ 2855 if (scp->term.num_param == 1) { 2856 scp->term.rev_color = 2857 (scp->term.rev_color & 0xF000) 2858 | ((scp->term.param[0] & 0x0F) << 8); 2859 scp->term.cur_attr = mask2attr(&scp->term); 2860 } 2861 break; 2862 2863 case 'I': /* set ansi reverse video background */ 2864 if (scp->term.num_param == 1) { 2865 scp->term.rev_color = 2866 (scp->term.rev_color & 0x0F00) 2867 | ((scp->term.param[0] & 0x0F) << 12); 2868 scp->term.cur_attr = mask2attr(&scp->term); 2869 } 2870 break; 2871 } 2872 } 2873#if notyet 2874 else if (scp->term.esc == 4) { /* seen ESC Q */ 2875 /* to be filled */ 2876 } 2877#endif 2878 else if (scp->term.esc == 5) { /* seen ESC ( */ 2879 switch (c) { 2880 case 'B': /* iso-2022: desginate ASCII into G0 */ 2881 break; 2882 /* other items to be filled */ 2883 default: 2884 break; 2885 } 2886 } 2887 scp->term.esc = 0; 2888} 2889 2890static void 2891ansi_put(scr_stat *scp, u_char *buf, int len) 2892{ 2893 u_char *ptr = buf; 2894 2895 /* make screensaver happy */ 2896 if (!sticky_splash && scp == cur_console) 2897 run_scrn_saver = FALSE; 2898 2899 write_in_progress++; 2900outloop: 2901 if (scp->term.esc) { 2902 scan_esc(scp, *ptr++); 2903 len--; 2904 } 2905 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2906 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2907 u_short cur_attr = scp->term.cur_attr; 2908 u_short *cursor_pos = scp->cursor_pos; 2909 do { 2910 /* 2911 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2912 * pointers in the following to volatile should have no effect, 2913 * but in fact speeds up this inner loop from 26 to 18 cycles 2914 * (+ cache misses) on i486's. 2915 */ 2916#define UCVP(ucp) ((u_char volatile *)(ucp)) 2917 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2918 ptr++; 2919 cnt--; 2920 } while (cnt && PRINTABLE(*ptr)); 2921 len -= (cursor_pos - scp->cursor_pos); 2922 scp->xpos += (cursor_pos - scp->cursor_pos); 2923 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2924 mark_for_update(scp, cursor_pos - scp->scr_buf); 2925 scp->cursor_pos = cursor_pos; 2926 if (scp->xpos >= scp->xsize) { 2927 scp->xpos = 0; 2928 scp->ypos++; 2929 } 2930 } 2931 else { 2932 switch(*ptr) { 2933 case 0x07: 2934 do_bell(scp, scp->bell_pitch, scp->bell_duration); 2935 break; 2936 2937 case 0x08: /* non-destructive backspace */ 2938 if (scp->cursor_pos > scp->scr_buf) { 2939 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2940 scp->cursor_pos--; 2941 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2942 if (scp->xpos > 0) 2943 scp->xpos--; 2944 else { 2945 scp->xpos += scp->xsize - 1; 2946 scp->ypos--; 2947 } 2948 } 2949 break; 2950 2951 case 0x09: /* non-destructive tab */ 2952 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2953 scp->cursor_pos += (8 - scp->xpos % 8u); 2954 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2955 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 2956 scp->xpos = 0; 2957 scp->ypos++; 2958 } 2959 break; 2960 2961 case 0x0a: /* newline, same pos */ 2962 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2963 scp->cursor_pos += scp->xsize; 2964 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2965 scp->ypos++; 2966 break; 2967 2968 case 0x0c: /* form feed, clears screen */ 2969 sc_clear_screen(scp); 2970 break; 2971 2972 case 0x0d: /* return, return to pos 0 */ 2973 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2974 scp->cursor_pos -= scp->xpos; 2975 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2976 scp->xpos = 0; 2977 break; 2978 2979 case 0x1b: /* start escape sequence */ 2980 scp->term.esc = 1; 2981 scp->term.num_param = 0; 2982 break; 2983 } 2984 ptr++; len--; 2985 } 2986 /* do we have to scroll ?? */ 2987 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 2988 remove_cutmarking(scp); 2989 if (scp->history != NULL) { 2990 bcopy(scp->scr_buf, scp->history_head, 2991 scp->xsize * sizeof(u_short)); 2992 scp->history_head += scp->xsize; 2993 if (scp->history_head + scp->xsize > 2994 scp->history + scp->history_size) 2995 scp->history_head = scp->history; 2996 } 2997 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 2998 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2999 fillw(scp->term.cur_color | scr_map[0x20], 3000 scp->scr_buf + scp->xsize * (scp->ysize - 1), 3001 scp->xsize); 3002 scp->cursor_pos -= scp->xsize; 3003 scp->ypos--; 3004 mark_all(scp); 3005 } 3006 if (len) 3007 goto outloop; 3008 write_in_progress--; 3009 if (delayed_next_scr) 3010 switch_scr(scp, delayed_next_scr - 1); 3011} 3012 3013static void 3014scinit(void) 3015{ 3016 int col; 3017 int row; 3018 u_int i; 3019 3020 if (init_done != COLD) 3021 return; 3022 init_done = WARM; 3023 3024 /* extract the hardware cursor location and move it out of the way */ 3025 (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row); 3026 (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1); 3027 3028 /* set up the first console */ 3029 current_default = &user_default; 3030 console[0] = &main_console; 3031 init_scp(console[0]); 3032 cur_console = console[0]; 3033 3034 /* copy screen to temporary buffer */ 3035 if (ISTEXTSC(console[0])) 3036 generic_bcopy((ushort *)(get_adapter(console[0])->va_window), sc_buffer, 3037 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 3038 3039 console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos 3040 = sc_buffer; 3041 if (col >= console[0]->xsize) 3042 col = 0; 3043 if (row >= console[0]->ysize) 3044 row = console[0]->ysize - 1; 3045 console[0]->xpos = col; 3046 console[0]->ypos = row; 3047 console[0]->cursor_pos = console[0]->cursor_oldpos = 3048 sc_buffer + row*console[0]->xsize + col; 3049 console[0]->cursor_saveunder = *console[0]->cursor_pos; 3050 for (i=1; i<MAXCONS; i++) 3051 console[i] = NULL; 3052 kernel_console.esc = 0; 3053 kernel_console.attr_mask = NORMAL_ATTR; 3054 kernel_console.cur_attr = 3055 kernel_console.cur_color = kernel_console.std_color = 3056 kernel_default.std_color; 3057 kernel_console.rev_color = kernel_default.rev_color; 3058 3059 /* initialize mapscrn arrays to a one to one map */ 3060 for (i=0; i<sizeof(scr_map); i++) { 3061 scr_map[i] = scr_rmap[i] = i; 3062 } 3063 3064 /* Save font and palette */ 3065 if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) { 3066 if (fonts_loaded & FONT_16) { 3067 copy_font(cur_console, LOAD, 16, font_16); 3068 } else { 3069 copy_font(cur_console, SAVE, 16, font_16); 3070 fonts_loaded = FONT_16; 3071 set_destructive_cursor(cur_console); 3072 } 3073 /* 3074 * FONT KLUDGE 3075 * Always use the font page #0. XXX 3076 */ 3077 (*biosvidsw.show_font)(cur_console->adp, 0); 3078 } 3079 save_palette(cur_console, palette); 3080 3081#ifdef SC_SPLASH_SCREEN 3082 /* put up the splash. */ 3083 scsplash_init(cur_console); 3084#endif 3085} 3086 3087static void 3088scshutdown(int howto, void *arg) 3089{ 3090 scsplash_stick(FALSE); 3091 run_scrn_saver = FALSE; 3092 if (!cold && cur_console->smode.mode == VT_AUTO 3093 && console[0]->smode.mode == VT_AUTO) 3094 switch_scr(cur_console, 0); 3095 shutdown_in_progress = TRUE; 3096} 3097 3098int 3099sc_clean_up(scr_stat *scp) 3100{ 3101 int error; 3102 3103 if ((error = wait_scrn_saver_stop())) 3104 return error; 3105 scp->status &= ~MOUSE_VISIBLE; 3106 remove_cutmarking(scp); 3107 return 0; 3108} 3109 3110void 3111sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) 3112{ 3113 if (scp->scr_buf) 3114 free(scp->scr_buf, M_DEVBUF); 3115 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 3116 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3117 3118 if (clear) { 3119 /* clear the screen and move the text cursor to the top-left position */ 3120 sc_clear_screen(scp); 3121 } else { 3122 /* retain the current cursor position, but adjust pointers */ 3123 move_crsr(scp, scp->xpos, scp->ypos); 3124 scp->cursor_oldpos = scp->cursor_pos; 3125 } 3126 3127 /* move the mouse cursor at the center of the screen */ 3128 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); 3129} 3130 3131void 3132sc_alloc_cut_buffer(scr_stat *scp, int wait) 3133{ 3134 if ((cut_buffer == NULL) 3135 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 3136 if (cut_buffer != NULL) 3137 free(cut_buffer, M_DEVBUF); 3138 cut_buffer_size = scp->xsize * scp->ysize + 1; 3139 cut_buffer = (u_char *)malloc(cut_buffer_size, 3140 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3141 if (cut_buffer != NULL) 3142 cut_buffer[0] = '\0'; 3143 } 3144} 3145 3146void 3147sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) 3148{ 3149 u_short *usp; 3150 3151 if (lines < scp->ysize) 3152 lines = scp->ysize; 3153 3154 usp = scp->history; 3155 scp->history = NULL; 3156 if (usp != NULL) { 3157 free(usp, M_DEVBUF); 3158 if (extra > 0) 3159 extra_history_size += extra; 3160 } 3161 3162 scp->history_size = lines * scp->xsize; 3163 if (lines > imax(sc_history_size, scp->ysize)) 3164 extra_history_size -= lines - imax(sc_history_size, scp->ysize); 3165 usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 3166 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3167 if (usp != NULL) 3168 bzero(usp, scp->history_size * sizeof(u_short)); 3169 scp->history_head = scp->history_pos = usp; 3170 scp->history = usp; 3171} 3172 3173static scr_stat 3174*alloc_scp() 3175{ 3176 scr_stat *scp; 3177 3178 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3179 init_scp(scp); 3180 sc_alloc_scr_buffer(scp, TRUE, TRUE); 3181 if (ISMOUSEAVAIL(get_adapter(scp)->va_flags)) 3182 sc_alloc_cut_buffer(scp, TRUE); 3183 sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); 3184/* SOS 3185 if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE) 3186 set_mode(scp); 3187*/ 3188 sc_clear_screen(scp); 3189 scp->cursor_saveunder = *scp->cursor_pos; 3190 return scp; 3191} 3192 3193static void 3194init_scp(scr_stat *scp) 3195{ 3196 video_info_t info; 3197 3198 scp->adp = V_ADP_PRIMARY; 3199 (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info); 3200 3201 scp->status = 0; 3202 scp->mode = scp->initial_mode = initial_video_mode; 3203 scp->scr_buf = NULL; 3204 if (info.vi_flags & V_INFO_GRAPHICS) { 3205 scp->status |= GRAPHICS_MODE; 3206 scp->xpixel = info.vi_width; 3207 scp->ypixel = info.vi_height; 3208 scp->xsize = info.vi_width/8; 3209 scp->ysize = info.vi_height/info.vi_cheight; 3210 scp->font_size = FONT_NONE; 3211 } else { 3212 scp->xsize = info.vi_width; 3213 scp->ysize = info.vi_height; 3214 scp->xpixel = scp->xsize*8; 3215 scp->ypixel = scp->ysize*info.vi_cheight; 3216 scp->font_size = info.vi_cheight; 3217 } 3218 scp->xoff = scp->yoff = 0; 3219 scp->xpos = scp->ypos = 0; 3220 scp->saved_xpos = scp->saved_ypos = -1; 3221 scp->start = scp->xsize * scp->ysize; 3222 scp->end = 0; 3223 scp->term.esc = 0; 3224 scp->term.attr_mask = NORMAL_ATTR; 3225 scp->term.cur_attr = 3226 scp->term.cur_color = scp->term.std_color = 3227 current_default->std_color; 3228 scp->term.rev_color = current_default->rev_color; 3229 scp->border = BG_BLACK; 3230 scp->cursor_start = *(u_int8_t *)pa_to_va(0x461); 3231 scp->cursor_end = *(u_int8_t *)pa_to_va(0x460); 3232 scp->mouse_xpos = scp->xsize*8/2; 3233 scp->mouse_ypos = scp->ysize*scp->font_size/2; 3234 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3235 scp->mouse_signal = 0; 3236 scp->mouse_pid = 0; 3237 scp->mouse_proc = NULL; 3238 scp->bell_pitch = BELL_PITCH; 3239 scp->bell_duration = BELL_DURATION; 3240 scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 3241 scp->status |= CURSOR_ENABLED; 3242 scp->pid = 0; 3243 scp->proc = NULL; 3244 scp->smode.mode = VT_AUTO; 3245 scp->history_head = scp->history_pos = scp->history = NULL; 3246 scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; 3247} 3248 3249static u_char 3250*get_fstr(u_int c, u_int *len) 3251{ 3252 u_int i; 3253 3254 if (!(c & FKEY)) 3255 return(NULL); 3256 i = (c & 0xFF) - F_FN; 3257 if (i > n_fkey_tab) 3258 return(NULL); 3259 *len = fkey_tab[i].len; 3260 return(fkey_tab[i].str); 3261} 3262 3263static void 3264history_to_screen(scr_stat *scp) 3265{ 3266 int i; 3267 3268 for (i=0; i<scp->ysize; i++) 3269 bcopy(scp->history + (((scp->history_pos - scp->history) + 3270 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 3271 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 3272 scp->xsize * sizeof(u_short)); 3273 mark_all(scp); 3274} 3275 3276static int 3277history_up_line(scr_stat *scp) 3278{ 3279 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 3280 scp->history_head) { 3281 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 3282 history_to_screen(scp); 3283 return 0; 3284 } 3285 else 3286 return -1; 3287} 3288 3289static int 3290history_down_line(scr_stat *scp) 3291{ 3292 if (scp->history_pos != scp->history_head) { 3293 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 3294 history_to_screen(scp); 3295 return 0; 3296 } 3297 else 3298 return -1; 3299} 3300 3301/* 3302 * scgetc(flags) - get character from keyboard. 3303 * If flags & SCGETC_CN, then avoid harmful side effects. 3304 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3305 * return NOKEY if there is nothing there. 3306 */ 3307static u_int 3308scgetc(u_int flags) 3309{ 3310 struct key_t *key; 3311 u_char scancode, keycode; 3312 u_int state, action; 3313 int c; 3314 static u_char esc_flag = 0, compose = 0; 3315 static u_int chr = 0; 3316 3317next_code: 3318 /* first see if there is something in the keyboard port */ 3319 if (flags & SCGETC_NONBLOCK) { 3320 c = read_kbd_data_no_wait(sc_kbdc); 3321 if (c == -1) 3322 return(NOKEY); 3323 } else { 3324 do { 3325 c = read_kbd_data(sc_kbdc); 3326 } while(c == -1); 3327 } 3328 scancode = (u_char)c; 3329 3330 /* make screensaver happy */ 3331 if (!(scancode & 0x80)) { 3332 scsplash_stick(FALSE); 3333 run_scrn_saver = FALSE; 3334 } 3335 3336 if (!(flags & SCGETC_CN)) { 3337 /* do the /dev/random device a favour */ 3338 add_keyboard_randomness(scancode); 3339 3340 if (cur_console->status & KBD_RAW_MODE) 3341 return scancode; 3342 } 3343 3344 keycode = scancode & 0x7F; 3345 switch (esc_flag) { 3346 case 0x00: /* normal scancode */ 3347 switch(scancode) { 3348 case 0xB8: /* left alt (compose key) */ 3349 if (compose) { 3350 compose = 0; 3351 if (chr > 255) { 3352 do_bell(cur_console, 3353 BELL_PITCH, BELL_DURATION); 3354 chr = 0; 3355 } 3356 } 3357 break; 3358 case 0x38: 3359 if (!compose) { 3360 compose = 1; 3361 chr = 0; 3362 } 3363 break; 3364 case 0xE0: 3365 case 0xE1: 3366 esc_flag = scancode; 3367 goto next_code; 3368 } 3369 break; 3370 case 0xE0: /* 0xE0 prefix */ 3371 esc_flag = 0; 3372 switch (keycode) { 3373 case 0x1C: /* right enter key */ 3374 keycode = 0x59; 3375 break; 3376 case 0x1D: /* right ctrl key */ 3377 keycode = 0x5A; 3378 break; 3379 case 0x35: /* keypad divide key */ 3380 keycode = 0x5B; 3381 break; 3382 case 0x37: /* print scrn key */ 3383 keycode = 0x5C; 3384 break; 3385 case 0x38: /* right alt key (alt gr) */ 3386 keycode = 0x5D; 3387 break; 3388 case 0x47: /* grey home key */ 3389 keycode = 0x5E; 3390 break; 3391 case 0x48: /* grey up arrow key */ 3392 keycode = 0x5F; 3393 break; 3394 case 0x49: /* grey page up key */ 3395 keycode = 0x60; 3396 break; 3397 case 0x4B: /* grey left arrow key */ 3398 keycode = 0x61; 3399 break; 3400 case 0x4D: /* grey right arrow key */ 3401 keycode = 0x62; 3402 break; 3403 case 0x4F: /* grey end key */ 3404 keycode = 0x63; 3405 break; 3406 case 0x50: /* grey down arrow key */ 3407 keycode = 0x64; 3408 break; 3409 case 0x51: /* grey page down key */ 3410 keycode = 0x65; 3411 break; 3412 case 0x52: /* grey insert key */ 3413 keycode = 0x66; 3414 break; 3415 case 0x53: /* grey delete key */ 3416 keycode = 0x67; 3417 break; 3418 3419 /* the following 3 are only used on the MS "Natural" keyboard */ 3420 case 0x5b: /* left Window key */ 3421 keycode = 0x69; 3422 break; 3423 case 0x5c: /* right Window key */ 3424 keycode = 0x6a; 3425 break; 3426 case 0x5d: /* menu key */ 3427 keycode = 0x6b; 3428 break; 3429 default: /* ignore everything else */ 3430 goto next_code; 3431 } 3432 break; 3433 case 0xE1: /* 0xE1 prefix */ 3434 esc_flag = 0; 3435 if (keycode == 0x1D) 3436 esc_flag = 0x1D; 3437 goto next_code; 3438 /* NOT REACHED */ 3439 case 0x1D: /* pause / break */ 3440 esc_flag = 0; 3441 if (keycode != 0x45) 3442 goto next_code; 3443 keycode = 0x68; 3444 break; 3445 } 3446 3447 if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE)) 3448 return (keycode | (scancode & 0x80)); 3449 3450 /* if scroll-lock pressed allow history browsing */ 3451 if (cur_console->history && cur_console->status & SLKED) { 3452 int i; 3453 3454 cur_console->status &= ~CURSOR_ENABLED; 3455 if (!(cur_console->status & BUFFER_SAVED)) { 3456 cur_console->status |= BUFFER_SAVED; 3457 cur_console->history_save = cur_console->history_head; 3458 3459 /* copy screen into top of history buffer */ 3460 for (i=0; i<cur_console->ysize; i++) { 3461 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 3462 cur_console->history_head, 3463 cur_console->xsize * sizeof(u_short)); 3464 cur_console->history_head += cur_console->xsize; 3465 if (cur_console->history_head + cur_console->xsize > 3466 cur_console->history + cur_console->history_size) 3467 cur_console->history_head=cur_console->history; 3468 } 3469 cur_console->history_pos = cur_console->history_head; 3470 history_to_screen(cur_console); 3471 } 3472 switch (scancode) { 3473 case 0x47: /* home key */ 3474 cur_console->history_pos = cur_console->history_head; 3475 history_to_screen(cur_console); 3476 goto next_code; 3477 3478 case 0x4F: /* end key */ 3479 cur_console->history_pos = 3480 WRAPHIST(cur_console, cur_console->history_head, 3481 cur_console->xsize*cur_console->ysize); 3482 history_to_screen(cur_console); 3483 goto next_code; 3484 3485 case 0x48: /* up arrow key */ 3486 if (history_up_line(cur_console)) 3487 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3488 goto next_code; 3489 3490 case 0x50: /* down arrow key */ 3491 if (history_down_line(cur_console)) 3492 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3493 goto next_code; 3494 3495 case 0x49: /* page up key */ 3496 for (i=0; i<cur_console->ysize; i++) 3497 if (history_up_line(cur_console)) { 3498 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3499 break; 3500 } 3501 goto next_code; 3502 3503 case 0x51: /* page down key */ 3504 for (i=0; i<cur_console->ysize; i++) 3505 if (history_down_line(cur_console)) { 3506 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3507 break; 3508 } 3509 goto next_code; 3510 } 3511 } 3512 3513 if (compose) { 3514 switch (scancode) { 3515 /* key pressed process it */ 3516 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 3517 chr = (scancode - 0x40) + chr*10; 3518 goto next_code; 3519 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 3520 chr = (scancode - 0x47) + chr*10; 3521 goto next_code; 3522 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 3523 chr = (scancode - 0x4E) + chr*10; 3524 goto next_code; 3525 case 0x52: /* keypad 0 */ 3526 chr *= 10; 3527 goto next_code; 3528 3529 /* key release, no interest here */ 3530 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 3531 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 3532 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 3533 case 0xD2: /* keypad 0 */ 3534 goto next_code; 3535 3536 case 0x38: /* left alt key */ 3537 break; 3538 default: 3539 if (chr) { 3540 compose = chr = 0; 3541 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3542 goto next_code; 3543 } 3544 break; 3545 } 3546 } 3547 3548 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 3549 if ((!agrs && (cur_console->status & ALKED)) 3550 || (agrs && !(cur_console->status & ALKED))) 3551 keycode += ALTGR_OFFSET; 3552 key = &key_map.key[keycode]; 3553 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 3554 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 3555 state ^= 1; 3556 3557 /* Check for make/break */ 3558 action = key->map[state]; 3559 if (scancode & 0x80) { /* key released */ 3560 if (key->spcl & (0x80>>state)) { 3561 switch (action) { 3562 case LSH: 3563 shfts &= ~1; 3564 break; 3565 case RSH: 3566 shfts &= ~2; 3567 break; 3568 case LCTR: 3569 ctls &= ~1; 3570 break; 3571 case RCTR: 3572 ctls &= ~2; 3573 break; 3574 case LALT: 3575 alts &= ~1; 3576 break; 3577 case RALT: 3578 alts &= ~2; 3579 break; 3580 case NLK: 3581 nlkcnt = 0; 3582 break; 3583 case CLK: 3584 clkcnt = 0; 3585 break; 3586 case SLK: 3587 slkcnt = 0; 3588 break; 3589 case ASH: 3590 agrs = 0; 3591 break; 3592 case ALK: 3593 alkcnt = 0; 3594 break; 3595 case META: 3596 metas = 0; 3597 break; 3598 } 3599 } 3600 if (chr && !compose) { 3601 action = chr; 3602 chr = 0; 3603 return(action); 3604 } 3605 } else { 3606 /* key pressed */ 3607 if (key->spcl & (0x80>>state)) { 3608 switch (action) { 3609 /* LOCKING KEYS */ 3610 case NLK: 3611 if (!nlkcnt) { 3612 nlkcnt++; 3613 if (cur_console->status & NLKED) 3614 cur_console->status &= ~NLKED; 3615 else 3616 cur_console->status |= NLKED; 3617 update_leds(cur_console->status); 3618 } 3619 break; 3620 case CLK: 3621 if (!clkcnt) { 3622 clkcnt++; 3623 if (cur_console->status & CLKED) 3624 cur_console->status &= ~CLKED; 3625 else 3626 cur_console->status |= CLKED; 3627 update_leds(cur_console->status); 3628 } 3629 break; 3630 case SLK: 3631 if (!slkcnt) { 3632 slkcnt++; 3633 if (cur_console->status & SLKED) { 3634 cur_console->status &= ~SLKED; 3635 if (cur_console->status & BUFFER_SAVED){ 3636 int i; 3637 u_short *ptr = cur_console->history_save; 3638 3639 for (i=0; i<cur_console->ysize; i++) { 3640 bcopy(ptr, 3641 cur_console->scr_buf + 3642 (cur_console->xsize*i), 3643 cur_console->xsize * sizeof(u_short)); 3644 ptr += cur_console->xsize; 3645 if (ptr + cur_console->xsize > 3646 cur_console->history + 3647 cur_console->history_size) 3648 ptr = cur_console->history; 3649 } 3650 cur_console->status &= ~BUFFER_SAVED; 3651 cur_console->history_head=cur_console->history_save; 3652 cur_console->status |= CURSOR_ENABLED; 3653 mark_all(cur_console); 3654 } 3655 scstart(VIRTUAL_TTY(get_scr_num())); 3656 } 3657 else 3658 cur_console->status |= SLKED; 3659 update_leds(cur_console->status); 3660 } 3661 break; 3662 case ALK: 3663 if (!alkcnt) { 3664 alkcnt++; 3665 if (cur_console->status & ALKED) 3666 cur_console->status &= ~ALKED; 3667 else 3668 cur_console->status |= ALKED; 3669 update_leds(cur_console->status); 3670 } 3671 break; 3672 3673 /* NON-LOCKING KEYS */ 3674 case NOP: 3675 break; 3676 case SPSC: 3677 /* force activatation/deactivation of the screen saver */ 3678 accents = 0; 3679 if (scrn_blanked <= 0) { 3680 run_scrn_saver = TRUE; 3681 scrn_time_stamp -= scrn_blank_time; 3682 } 3683#ifdef SC_SPLASH_SCREEN 3684 if (cold) { 3685 /* 3686 * While devices are being probed, the screen saver need 3687 * to be invoked explictly. XXX 3688 */ 3689 if (scrn_blanked > 0) { 3690 scsplash_stick(FALSE); 3691 stop_scrn_saver(current_saver); 3692 } else { 3693 if (!ISGRAPHSC(cur_console)) { 3694 scsplash_stick(TRUE); 3695 scrn_saver(current_saver, TRUE); 3696 } 3697 } 3698 } 3699#endif 3700 break; 3701 case RBT: 3702#ifndef SC_DISABLE_REBOOT 3703 accents = 0; 3704 shutdown_nice(); 3705#endif 3706 break; 3707 case SUSP: 3708#if NAPM > 0 3709 accents = 0; 3710 apm_suspend(PMST_SUSPEND); 3711#endif 3712 break; 3713 3714 case STBY: 3715#if NAPM > 0 3716 accents = 0; 3717 apm_suspend(PMST_STANDBY); 3718#endif 3719 break; 3720 3721 case DBG: 3722#ifdef DDB /* try to switch to console 0 */ 3723 accents = 0; 3724 /* 3725 * TRY to make sure the screen saver is stopped, 3726 * and the screen is updated before switching to 3727 * the vty0. 3728 */ 3729 scrn_timer((void *)FALSE); 3730 if (cur_console->smode.mode == VT_AUTO && 3731 console[0]->smode.mode == VT_AUTO) 3732 switch_scr(cur_console, 0); 3733 Debugger("manual escape to debugger"); 3734#else 3735 printf("No debugger in kernel\n"); 3736#endif 3737 break; 3738 case LSH: 3739 shfts |= 1; 3740 break; 3741 case RSH: 3742 shfts |= 2; 3743 break; 3744 case LCTR: 3745 ctls |= 1; 3746 break; 3747 case RCTR: 3748 ctls |= 2; 3749 break; 3750 case LALT: 3751 alts |= 1; 3752 break; 3753 case RALT: 3754 alts |= 2; 3755 break; 3756 case ASH: 3757 agrs = 1; 3758 break; 3759 case META: 3760 metas = 1; 3761 break; 3762 case NEXT: 3763 { 3764 int next, this = get_scr_num(); 3765 accents = 0; 3766 for (next = this+1; next != this; next = (next+1)%MAXCONS) { 3767 struct tty *tp = VIRTUAL_TTY(next); 3768 if (tp->t_state & TS_ISOPEN) { 3769 switch_scr(cur_console, next); 3770 break; 3771 } 3772 } 3773 } 3774 break; 3775 case BTAB: 3776 accents = 0; 3777 return(BKEY); 3778 default: 3779 if (action >= F_ACC && action <= L_ACC) { 3780 /* turn it into an index */ 3781 action -= F_ACC - 1; 3782 if ((action > accent_map.n_accs) 3783 || (accent_map.acc[action - 1].accchar == 0)) { 3784 /* 3785 * The index is out of range or pointing to an 3786 * empty entry. 3787 */ 3788 accents = 0; 3789 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3790 } 3791 /* 3792 * If the same accent key has been hit twice, 3793 * produce the accent char itself. 3794 */ 3795 if (action == accents) { 3796 action = accent_map.acc[accents - 1].accchar; 3797 accents = 0; 3798 if (metas) 3799 action |= MKEY; 3800 return (action); 3801 } 3802 /* remember the index and wait for the next key stroke */ 3803 accents = action; 3804 break; 3805 } 3806 if (accents > 0) { 3807 accents = 0; 3808 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3809 } 3810 if (action >= F_SCR && action <= L_SCR) { 3811 switch_scr(cur_console, action - F_SCR); 3812 break; 3813 } 3814 if (action >= F_FN && action <= L_FN) 3815 action |= FKEY; 3816 return(action); 3817 } 3818 } 3819 else { 3820 if (accents) { 3821 struct acc_t *acc; 3822 int i; 3823 3824 acc = &accent_map.acc[accents - 1]; 3825 accents = 0; 3826 /* 3827 * If the accent key is followed by the space key, 3828 * produce the accent char itself. 3829 */ 3830 if (action == ' ') { 3831 action = acc->accchar; 3832 if (metas) 3833 action |= MKEY; 3834 return (action); 3835 } 3836 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 3837 if (acc->map[i][0] == 0) /* end of the map entry */ 3838 break; 3839 if (acc->map[i][0] == action) { 3840 action = acc->map[i][1]; 3841 if (metas) 3842 action |= MKEY; 3843 return (action); 3844 } 3845 } 3846 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3847 goto next_code; 3848 } 3849 if (metas) 3850 action |= MKEY; 3851 return(action); 3852 } 3853 } 3854 goto next_code; 3855} 3856 3857int 3858scmmap(dev_t dev, vm_offset_t offset, int nprot) 3859{ 3860 if (offset > 0x20000 - PAGE_SIZE) 3861 return -1; 3862 return i386_btop((VIDEOMEM + offset)); 3863} 3864 3865/* 3866 * Calculate hardware attributes word using logical attributes mask and 3867 * hardware colors 3868 */ 3869 3870static int 3871mask2attr(struct term_stat *term) 3872{ 3873 int attr, mask = term->attr_mask; 3874 3875 if (mask & REVERSE_ATTR) { 3876 attr = ((mask & FOREGROUND_CHANGED) ? 3877 ((term->cur_color & 0xF000) >> 4) : 3878 (term->rev_color & 0x0F00)) | 3879 ((mask & BACKGROUND_CHANGED) ? 3880 ((term->cur_color & 0x0F00) << 4) : 3881 (term->rev_color & 0xF000)); 3882 } else 3883 attr = term->cur_color; 3884 3885 /* XXX: underline mapping for Hercules adapter can be better */ 3886 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3887 attr ^= 0x0800; 3888 if (mask & BLINK_ATTR) 3889 attr ^= 0x8000; 3890 3891 return attr; 3892} 3893 3894static void 3895set_keyboard(int command, int data) 3896{ 3897 int s; 3898 3899 if (sc_kbdc == NULL) 3900 return; 3901 3902 /* prevent the timeout routine from polling the keyboard */ 3903 if (!kbdc_lock(sc_kbdc, TRUE)) 3904 return; 3905 3906 /* disable the keyboard and mouse interrupt */ 3907 s = spltty(); 3908#if 0 3909 c = get_controller_command_byte(sc_kbdc); 3910 if ((c == -1) 3911 || !set_controller_command_byte(sc_kbdc, 3912 kbdc_get_device_mask(sc_kbdc), 3913 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 3914 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 3915 /* CONTROLLER ERROR */ 3916 kbdc_lock(sc_kbdc, FALSE); 3917 splx(s); 3918 return; 3919 } 3920 /* 3921 * Now that the keyboard controller is told not to generate 3922 * the keyboard and mouse interrupts, call `splx()' to allow 3923 * the other tty interrupts. The clock interrupt may also occur, 3924 * but the timeout routine (`scrn_timer()') will be blocked 3925 * by the lock flag set via `kbdc_lock()' 3926 */ 3927 splx(s); 3928#endif 3929 3930 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) 3931 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); 3932 3933#if 0 3934 /* restore the interrupts */ 3935 if (!set_controller_command_byte(sc_kbdc, 3936 kbdc_get_device_mask(sc_kbdc), 3937 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 3938 /* CONTROLLER ERROR */ 3939 } 3940#else 3941 splx(s); 3942#endif 3943 kbdc_lock(sc_kbdc, FALSE); 3944} 3945 3946static void 3947update_leds(int which) 3948{ 3949 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 3950 3951 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 3952 if (key_map.n_keys > ALTGR_OFFSET) { 3953 if (which & ALKED) 3954 which |= CLKED; 3955 else 3956 which &= ~CLKED; 3957 } 3958 3959 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); 3960} 3961 3962int 3963set_mode(scr_stat *scp) 3964{ 3965 video_info_t info; 3966 video_adapter_t *adp; 3967 3968 /* reject unsupported mode */ 3969 if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) 3970 return 1; 3971 3972 /* if this vty is not currently showing, do nothing */ 3973 if (scp != cur_console) 3974 return 0; 3975 3976 /* setup video hardware for the given mode */ 3977 adp = get_adapter(scp); 3978 (*biosvidsw.set_mode)(scp->adp, scp->mode); 3979 Crtat = (u_short *)adp->va_window; 3980 3981 if (!(scp->status & GRAPHICS_MODE)) { 3982 /* load appropriate font */ 3983 if (!(scp->status & PIXEL_MODE) 3984 && ISFONTAVAIL(get_adapter(scp)->va_flags)) { 3985 if (scp->font_size < 14) { 3986 if (fonts_loaded & FONT_8) 3987 copy_font(scp, LOAD, 8, font_8); 3988 } else if (scp->font_size >= 16) { 3989 if (fonts_loaded & FONT_16) 3990 copy_font(scp, LOAD, 16, font_16); 3991 } else { 3992 if (fonts_loaded & FONT_14) 3993 copy_font(scp, LOAD, 14, font_14); 3994 } 3995 /* 3996 * FONT KLUDGE: 3997 * This is an interim kludge to display correct font. 3998 * Always use the font page #0 on the video plane 2. 3999 * Somehow we cannot show the font in other font pages on 4000 * some video cards... XXX 4001 */ 4002 (*biosvidsw.show_font)(scp->adp, 0); 4003 } 4004 mark_all(scp); 4005 } 4006 4007 if (scp->status & PIXEL_MODE) 4008 generic_bzero((u_char *)(adp->va_window), scp->xpixel*scp->ypixel/8); 4009 set_border(scp, scp->border); 4010 4011 /* move hardware cursor out of the way */ 4012 (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); 4013 4014 return 0; 4015} 4016 4017void 4018set_border(scr_stat *scp, int color) 4019{ 4020 u_char *p; 4021 int xoff; 4022 int yoff; 4023 int xlen; 4024 int ylen; 4025 int i; 4026 4027 (*biosvidsw.set_border)(scp->adp, color); 4028 4029 if (scp->status & PIXEL_MODE) { 4030 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4031 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4032 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4033 outw(GDCIDX, 0xff08); /* bit mask */ 4034 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 4035 p = (u_char *)(get_adapter(scp)->va_window); 4036 xoff = scp->xoff; 4037 yoff = scp->yoff*scp->font_size; 4038 xlen = scp->xpixel/8; 4039 ylen = scp->ysize*scp->font_size; 4040 if (yoff > 0) { 4041 generic_bzero(p, xlen*yoff); 4042 generic_bzero(p + xlen*(yoff + ylen), 4043 xlen*scp->ypixel - xlen*(yoff + ylen)); 4044 } 4045 if (xoff > 0) { 4046 for (i = 0; i < ylen; ++i) { 4047 generic_bzero(p + xlen*(yoff + i), xoff); 4048 generic_bzero(p + xlen*(yoff + i) + xoff + scp->xsize, 4049 xlen - xoff - scp->xsize); 4050 } 4051 } 4052 outw(GDCIDX, 0x0000); /* set/reset */ 4053 outw(GDCIDX, 0x0001); /* set/reset enable */ 4054 } 4055} 4056 4057void 4058copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) 4059{ 4060 /* 4061 * FONT KLUDGE: 4062 * This is an interim kludge to display correct font. 4063 * Always use the font page #0 on the video plane 2. 4064 * Somehow we cannot show the font in other font pages on 4065 * some video cards... XXX 4066 */ 4067 font_loading_in_progress = TRUE; 4068 if (operation == LOAD) { 4069 (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256); 4070 if (sc_flags & CHAR_CURSOR) 4071 set_destructive_cursor(scp); 4072 } else if (operation == SAVE) { 4073 (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256); 4074 } 4075 font_loading_in_progress = FALSE; 4076} 4077 4078static void 4079set_destructive_cursor(scr_stat *scp) 4080{ 4081 u_char cursor[32]; 4082 u_char *font_buffer; 4083 int font_size; 4084 int i; 4085 4086 if (!ISFONTAVAIL(get_adapter(scp)->va_flags) 4087 || (scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 4088 return; 4089 4090 if (scp->font_size < 14) { 4091 font_buffer = font_8; 4092 font_size = 8; 4093 } else if (scp->font_size >= 16) { 4094 font_buffer = font_16; 4095 font_size = 16; 4096 } else { 4097 font_buffer = font_14; 4098 font_size = 14; 4099 } 4100 4101 if (scp->status & MOUSE_VISIBLE) { 4102 if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) 4103 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 4104 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1) 4105 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 4106 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2) 4107 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 4108 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3) 4109 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 4110 else 4111 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 4112 cursor, scp->font_size); 4113 } 4114 else 4115 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 4116 cursor, scp->font_size); 4117 for (i=0; i<32; i++) 4118 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 4119 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 4120 cursor[i] |= 0xff; 4121#if 1 4122 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 4123#endif 4124 font_loading_in_progress = TRUE; 4125 (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); 4126 font_loading_in_progress = FALSE; 4127} 4128 4129void 4130sc_move_mouse(scr_stat *scp, int x, int y) 4131{ 4132 scp->mouse_xpos = x; 4133 scp->mouse_ypos = y; 4134 scp->mouse_pos = scp->mouse_oldpos = 4135 scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8; 4136} 4137 4138static void 4139set_mouse_pos(scr_stat *scp) 4140{ 4141 static int last_xpos = -1, last_ypos = -1; 4142 4143 if (scp->mouse_xpos < 0) 4144 scp->mouse_xpos = 0; 4145 if (scp->mouse_ypos < 0) 4146 scp->mouse_ypos = 0; 4147 if (!ISTEXTSC(scp)) { 4148 if (scp->mouse_xpos > scp->xpixel-1) 4149 scp->mouse_xpos = scp->xpixel-1; 4150 if (scp->mouse_ypos > scp->ypixel-1) 4151 scp->mouse_ypos = scp->ypixel-1; 4152 return; 4153 } 4154 if (scp->mouse_xpos > (scp->xsize*8)-1) 4155 scp->mouse_xpos = (scp->xsize*8)-1; 4156 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) 4157 scp->mouse_ypos = (scp->ysize*scp->font_size)-1; 4158 4159 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 4160 scp->status |= MOUSE_MOVED; 4161 4162 scp->mouse_pos = scp->scr_buf + 4163 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 4164 4165 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 4166 mouse_cut(scp); 4167 } 4168} 4169 4170#define isspace(c) (((c) & 0xff) == ' ') 4171 4172static int 4173skip_spc_right(scr_stat *scp, u_short *p) 4174{ 4175 int i; 4176 4177 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4178 if (!isspace(*p)) 4179 break; 4180 ++p; 4181 } 4182 return i; 4183} 4184 4185static int 4186skip_spc_left(scr_stat *scp, u_short *p) 4187{ 4188 int i; 4189 4190 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { 4191 if (!isspace(*p)) 4192 break; 4193 --p; 4194 } 4195 return i; 4196} 4197 4198static void 4199mouse_cut(scr_stat *scp) 4200{ 4201 u_short *end; 4202 u_short *p; 4203 int i = 0; 4204 int j = 0; 4205 4206 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? 4207 scp->mouse_pos + 1 : scp->mouse_pos; 4208 end = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4209 scp->mouse_cut_start : scp->mouse_cut_end; 4210 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4211 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { 4212 cut_buffer[i] = *p & 0xff; 4213 /* remember the position of the last non-space char */ 4214 if (!isspace(cut_buffer[i++])) 4215 j = i; 4216 /* trim trailing blank when crossing lines */ 4217 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 4218 cut_buffer[j++] = '\r'; 4219 i = j; 4220 } 4221 } 4222 cut_buffer[i] = '\0'; 4223 4224 /* scan towards the end of the last line */ 4225 --p; 4226 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4227 if (!isspace(*p)) 4228 break; 4229 ++p; 4230 } 4231 /* if there is nothing but blank chars, trim them, but mark towards eol */ 4232 if (i >= scp->xsize) { 4233 if (scp->mouse_cut_start > scp->mouse_cut_end) 4234 scp->mouse_cut_start = p; 4235 else 4236 scp->mouse_cut_end = p; 4237 cut_buffer[j++] = '\r'; 4238 cut_buffer[j] = '\0'; 4239 } 4240 4241 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 4242 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 4243} 4244 4245static void 4246mouse_cut_start(scr_stat *scp) 4247{ 4248 int i; 4249 4250 if (scp->status & MOUSE_VISIBLE) { 4251 if (scp->mouse_pos == scp->mouse_cut_start && 4252 scp->mouse_cut_start == scp->mouse_cut_end - 1) { 4253 cut_buffer[0] = '\0'; 4254 remove_cutmarking(scp); 4255 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 4256 /* if the pointer is on trailing blank chars, mark towards eol */ 4257 i = skip_spc_left(scp, scp->mouse_pos) + 1; 4258 scp->mouse_cut_start = scp->scr_buf + 4259 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; 4260 scp->mouse_cut_end = scp->scr_buf + 4261 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; 4262 cut_buffer[0] = '\r'; 4263 cut_buffer[1] = '\0'; 4264 scp->status |= MOUSE_CUTTING; 4265 } else { 4266 scp->mouse_cut_start = scp->mouse_pos; 4267 scp->mouse_cut_end = scp->mouse_cut_start + 1; 4268 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 4269 cut_buffer[1] = '\0'; 4270 scp->status |= MOUSE_CUTTING; 4271 } 4272 mark_all(scp); 4273 /* delete all other screens cut markings */ 4274 for (i=0; i<MAXCONS; i++) { 4275 if (console[i] == NULL || console[i] == scp) 4276 continue; 4277 remove_cutmarking(console[i]); 4278 } 4279 } 4280} 4281 4282static void 4283mouse_cut_end(scr_stat *scp) 4284{ 4285 if (scp->status & MOUSE_VISIBLE) { 4286 scp->status &= ~MOUSE_CUTTING; 4287 } 4288} 4289 4290static void 4291mouse_cut_word(scr_stat *scp) 4292{ 4293 u_short *p; 4294 u_short *sol; 4295 u_short *eol; 4296 int i; 4297 4298 /* 4299 * Because we don't have locale information in the kernel, 4300 * we only distinguish space char and non-space chars. Punctuation 4301 * chars, symbols and other regular chars are all treated alike. 4302 */ 4303 if (scp->status & MOUSE_VISIBLE) { 4304 sol = scp->scr_buf 4305 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4306 eol = sol + scp->xsize; 4307 if (isspace(*scp->mouse_pos)) { 4308 for (p = scp->mouse_pos; p >= sol; --p) 4309 if (!isspace(*p)) 4310 break; 4311 scp->mouse_cut_start = ++p; 4312 for (p = scp->mouse_pos; p < eol; ++p) 4313 if (!isspace(*p)) 4314 break; 4315 scp->mouse_cut_end = p; 4316 } else { 4317 for (p = scp->mouse_pos; p >= sol; --p) 4318 if (isspace(*p)) 4319 break; 4320 scp->mouse_cut_start = ++p; 4321 for (p = scp->mouse_pos; p < eol; ++p) 4322 if (isspace(*p)) 4323 break; 4324 scp->mouse_cut_end = p; 4325 } 4326 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4327 cut_buffer[i++] = *p & 0xff; 4328 cut_buffer[i] = '\0'; 4329 scp->status |= MOUSE_CUTTING; 4330 } 4331} 4332 4333static void 4334mouse_cut_line(scr_stat *scp) 4335{ 4336 u_short *p; 4337 int i; 4338 4339 if (scp->status & MOUSE_VISIBLE) { 4340 scp->mouse_cut_start = scp->scr_buf 4341 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4342 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; 4343 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4344 cut_buffer[i++] = *p & 0xff; 4345 cut_buffer[i++] = '\r'; 4346 cut_buffer[i] = '\0'; 4347 scp->status |= MOUSE_CUTTING; 4348 } 4349} 4350 4351static void 4352mouse_cut_extend(scr_stat *scp) 4353{ 4354 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 4355 && (scp->mouse_cut_start != NULL)) { 4356 mouse_cut(scp); 4357 scp->status |= MOUSE_CUTTING; 4358 } 4359} 4360 4361static void 4362mouse_paste(scr_stat *scp) 4363{ 4364 if (scp->status & MOUSE_VISIBLE) { 4365 struct tty *tp; 4366 u_char *ptr = cut_buffer; 4367 4368 tp = VIRTUAL_TTY(get_scr_num()); 4369 while (*ptr) 4370 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 4371 } 4372} 4373 4374static void 4375draw_mouse_image(scr_stat *scp) 4376{ 4377 u_short buffer[32]; 4378 u_short xoffset, yoffset; 4379 u_short *crt_pos = (u_short *)(get_adapter(scp)->va_window) 4380 + (scp->mouse_pos - scp->scr_buf); 4381 u_char *font_buffer; 4382 int font_size; 4383 int i; 4384 4385 if (scp->font_size < 14) { 4386 font_buffer = font_8; 4387 font_size = 8; 4388 } else if (scp->font_size >= 16) { 4389 font_buffer = font_16; 4390 font_size = 16; 4391 } else { 4392 font_buffer = font_14; 4393 font_size = 14; 4394 } 4395 4396 xoffset = scp->mouse_xpos % 8; 4397 yoffset = scp->mouse_ypos % scp->font_size; 4398 4399 /* prepare mousepointer char's bitmaps */ 4400 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 4401 &scp->mouse_cursor[0], font_size); 4402 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 4403 &scp->mouse_cursor[32], font_size); 4404 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 4405 &scp->mouse_cursor[64], font_size); 4406 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 4407 &scp->mouse_cursor[96], font_size); 4408 for (i=0; i<font_size; i++) { 4409 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 4410 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 4411 } 4412 4413 /* now and-or in the mousepointer image */ 4414 for (i=0; i<16; i++) { 4415 buffer[i+yoffset] = 4416 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 4417 | (mouse_or_mask[i] >> xoffset); 4418 } 4419 for (i=0; i<font_size; i++) { 4420 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 4421 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 4422 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 4423 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 4424 } 4425 4426 scp->mouse_oldpos = scp->mouse_pos; 4427 4428#if 1 4429 /* wait for vertical retrace to avoid jitter on some videocards */ 4430 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 4431#endif 4432 font_loading_in_progress = TRUE; 4433 (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, 4434 SC_MOUSE_CHAR, 4); 4435 font_loading_in_progress = FALSE; 4436 4437 *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR; 4438 *(crt_pos+scp->xsize) = 4439 (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2); 4440 if (scp->mouse_xpos < (scp->xsize-1)*8) { 4441 *(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1); 4442 *(crt_pos+scp->xsize + 1) = 4443 (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3); 4444 } 4445 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 4446 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 4447} 4448 4449static void 4450remove_mouse_image(scr_stat *scp) 4451{ 4452 u_short *crt_pos; 4453 4454 if (!ISTEXTSC(scp)) 4455 return; 4456 4457 crt_pos = (u_short *)(get_adapter(scp)->va_window) 4458 + (scp->mouse_oldpos - scp->scr_buf); 4459 *(crt_pos) = *(scp->mouse_oldpos); 4460 *(crt_pos+1) = *(scp->mouse_oldpos+1); 4461 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 4462 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 4463 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 4464 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 4465} 4466 4467static void 4468draw_cutmarking(scr_stat *scp) 4469{ 4470 u_short *crt_pos; 4471 u_short *ptr; 4472 u_short och, nch; 4473 4474 crt_pos = (u_short *)(get_adapter(scp)->va_window); 4475 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 4476 nch = och = *(crt_pos + (ptr - scp->scr_buf)); 4477 /* are we outside the selected area ? */ 4478 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 4479 scp->mouse_cut_end : scp->mouse_cut_start) || 4480 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? 4481 scp->mouse_cut_start : scp->mouse_cut_end)) { 4482 if (ptr != scp->cursor_pos) 4483 nch = (och & 0xff) | (*ptr & 0xff00); 4484 } 4485 else { 4486 /* are we clear of the cursor image ? */ 4487 if (ptr != scp->cursor_pos) 4488 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 4489 else { 4490 if (sc_flags & CHAR_CURSOR) 4491 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 4492 else 4493 if (!(sc_flags & BLINK_CURSOR)) 4494 nch = (och & 0xff) | (*ptr & 0xff00); 4495 } 4496 } 4497 if (nch != och) 4498 *(crt_pos + (ptr - scp->scr_buf)) = nch; 4499 } 4500} 4501 4502static void 4503remove_cutmarking(scr_stat *scp) 4504{ 4505 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 4506 scp->status &= ~MOUSE_CUTTING; 4507 mark_all(scp); 4508} 4509 4510static void 4511do_bell(scr_stat *scp, int pitch, int duration) 4512{ 4513 if (cold || shutdown_in_progress) 4514 return; 4515 4516 if (scp != cur_console && (sc_flags & QUIET_BELL)) 4517 return; 4518 4519 if (sc_flags & VISUAL_BELL) { 4520 if (blink_in_progress) 4521 return; 4522 blink_in_progress = 4; 4523 if (scp != cur_console) 4524 blink_in_progress += 2; 4525 blink_screen(cur_console); 4526 } else { 4527 if (scp != cur_console) 4528 pitch *= 2; 4529 sysbeep(pitch, duration); 4530 } 4531} 4532 4533static void 4534blink_screen(void *arg) 4535{ 4536 scr_stat *scp = arg; 4537 4538 if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { 4539 blink_in_progress = FALSE; 4540 mark_all(scp); 4541 if (delayed_next_scr) 4542 switch_scr(scp, delayed_next_scr - 1); 4543 } 4544 else { 4545 if (blink_in_progress & 1) 4546 fillw(kernel_default.std_color | scr_map[0x20], 4547 (u_short *)(get_adapter(scp)->va_window), 4548 scp->xsize * scp->ysize); 4549 else 4550 fillw(kernel_default.rev_color | scr_map[0x20], 4551 (u_short *)(get_adapter(scp)->va_window), 4552 scp->xsize * scp->ysize); 4553 blink_in_progress--; 4554 timeout(blink_screen, scp, hz / 10); 4555 } 4556} 4557 4558void 4559sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) 4560{ 4561 u_char *font; 4562 u_char volatile *d; 4563 u_char *e; 4564 u_char *f; 4565 int font_size; 4566 int line_length; 4567 int xsize; 4568 u_short bg; 4569 int i, j; 4570 u_char c; 4571 4572 if (ISTEXTSC(scp)) { 4573 generic_bcopy(p + from, (u_short *)(get_adapter(scp)->va_window) + from, 4574 (to - from + 1)*sizeof(u_short)); 4575 } else /* if ISPIXELSC(scp) */ { 4576 if (mark) 4577 mark = 255; 4578 font_size = scp->font_size; 4579 if (font_size < 14) 4580 font = font_8; 4581 else if (font_size >= 16) 4582 font = font_16; 4583 else 4584 font = font_14; 4585 line_length = scp->xpixel/8; 4586 xsize = scp->xsize; 4587 d = (u_char *)(get_adapter(scp)->va_window) 4588 + scp->xoff + scp->yoff*font_size*line_length 4589 + (from%xsize) + font_size*line_length*(from/xsize); 4590 4591 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4592 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4593 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4594 bg = -1; 4595 for (i = from ; i <= to ; i++) { 4596 /* set background color in EGA/VGA latch */ 4597 if (bg != (p[i] & 0xf000)) { 4598 bg = (p[i] & 0xf000); 4599 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4600 outw(GDCIDX, 0xff08); /* bit mask */ 4601 *d = 0; 4602 c = *d; /* set the background color in the latch */ 4603 } 4604 /* foreground color */ 4605 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4606 e = (u_char *)d; 4607 f = &font[(p[i] & 0x00ff)*font_size]; 4608 for (j = 0 ; j < font_size; j++, f++) { 4609 outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */ 4610 *e = 0; 4611 e += line_length; 4612 } 4613 d++; 4614 if ((i % xsize) == xsize - 1) 4615 d += scp->xoff*2 + (font_size - 1)*line_length; 4616 } 4617 outw(GDCIDX, 0x0000); /* set/reset */ 4618 outw(GDCIDX, 0x0001); /* set/reset enable */ 4619 outw(GDCIDX, 0xff08); /* bit mask */ 4620 4621#if 0 /* VGA only */ 4622 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4623 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4624 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4625 outw(GDCIDX, 0xff08); /* bit mask */ 4626 bg = -1; 4627 for (i = from ; i <= to ; i++) { 4628 /* set background color in EGA/VGA latch */ 4629 if (bg != (p[i] & 0xf000)) { 4630 bg = (p[i] & 0xf000); 4631 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4632 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4633 *d = 0; 4634 c = *d; /* set the background color in the latch */ 4635 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4636 } 4637 /* foreground color */ 4638 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4639 e = (u_char *)d; 4640 f = &font[(p[i] & 0x00ff)*font_size]; 4641 for (j = 0 ; j < font_size; j++, f++) { 4642 *e = *f^mark; 4643 e += line_length; 4644 } 4645 d++; 4646 if ((i % xsize) == xsize - 1) 4647 d += scp->xoff*2 + (font_size - 1)*line_length; 4648 } 4649 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4650 outw(GDCIDX, 0x0000); /* set/reset */ 4651 outw(GDCIDX, 0x0001); /* set/reset enable */ 4652#endif /* 0 */ 4653 } 4654} 4655 4656#ifdef SC_SPLASH_SCREEN 4657 4658static void 4659scsplash_init(scr_stat *scp) 4660{ 4661 video_info_t info; 4662 4663 if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) { 4664 default_saver = scsplash_saver; 4665 scrn_blank_time = DEFAULT_BLANKTIME; 4666 run_scrn_saver = TRUE; 4667 if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) { 4668 scsplash_stick(TRUE); 4669 scsplash_saver(TRUE); 4670 } 4671 } 4672} 4673 4674static void 4675scsplash_term(scr_stat *scp) 4676{ 4677 default_saver = none_saver; 4678 scsplash_stick(FALSE); 4679 remove_scrn_saver(scsplash_saver); 4680 scsplash_unload(scp); 4681} 4682 4683static void 4684scsplash_saver(int show) 4685{ 4686 if (show) 4687 scsplash(TRUE); 4688 else if (!sticky_splash) 4689 scsplash(FALSE); 4690} 4691 4692#endif /* SC_SPLASH_SCREEN */ 4693 4694#endif /* NSC */ 4695