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