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