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