syscons.c revision 47034
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.302 1999/05/10 14:01:32 dfr 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 240static const int nsccons = MAXCONS+2; 241 242#define WRAPHIST(scp, pointer, offset) \ 243 ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ 244 + (offset)) % (scp)->history_size)) 245#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 246 247/* some useful macros */ 248#define kbd_read_char(kbd, wait) \ 249 (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait)) 250#define kbd_check_char(kbd) \ 251 (*kbdsw[(kbd)->kb_index]->check_char)((kbd)) 252#define kbd_enable(kbd) \ 253 (*kbdsw[(kbd)->kb_index]->enable)((kbd)) 254#define kbd_disable(kbd) \ 255 (*kbdsw[(kbd)->kb_index]->disable)((kbd)) 256#define kbd_lock(kbd, lockf) \ 257 (*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf)) 258#define kbd_ioctl(kbd, cmd, arg) \ 259 (((kbd) == NULL) ? \ 260 ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg))) 261#define kbd_clear_state(kbd) \ 262 (*kbdsw[(kbd)->kb_index]->clear_state)((kbd)) 263#define kbd_get_fkeystr(kbd, fkey, len) \ 264 (*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len)) 265#define kbd_poll(kbd, on) \ 266 (*kbdsw[(kbd)->kb_index]->poll)((kbd), (on)) 267 268/* prototypes */ 269static kbd_callback_func_t sckbdevent; 270static int scparam(struct tty *tp, struct termios *t); 271static int scvidprobe(int unit, int flags, int cons); 272static int sckbdprobe(int unit, int flags, int cons); 273static void scstart(struct tty *tp); 274static void scmousestart(struct tty *tp); 275static void scinit(void); 276static void scshutdown(int howto, void *arg); 277static u_int scgetc(keyboard_t *kbd, u_int flags); 278#define SCGETC_CN 1 279#define SCGETC_NONBLOCK 2 280static int sccngetch(int flags); 281static void sccnupdate(scr_stat *scp); 282static scr_stat *alloc_scp(void); 283static void init_scp(scr_stat *scp); 284static void get_bios_values(void); 285static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); 286static int get_scr_num(void); 287static timeout_t scrn_timer; 288static void scrn_update(scr_stat *scp, int show_cursor); 289#if NSPLASH > 0 290static int scsplash_callback(int); 291static void scsplash_saver(int show); 292static int add_scrn_saver(void (*this_saver)(int)); 293static int remove_scrn_saver(void (*this_saver)(int)); 294static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border); 295static int restore_scrn_saver_mode(scr_stat *scp, int changemode); 296static void stop_scrn_saver(void (*saver)(int)); 297static int wait_scrn_saver_stop(void); 298#define scsplash_stick(stick) (sticky_splash = (stick)) 299#else /* !NSPLASH */ 300#define stop_scrn_saver(saver) 301#define wait_scrn_saver_stop() 0 302#define scsplash_stick(stick) 303#endif /* NSPLASH */ 304static int switch_scr(scr_stat *scp, u_int next_scr); 305static void exchange_scr(void); 306static void scan_esc(scr_stat *scp, u_char c); 307static void ansi_put(scr_stat *scp, u_char *buf, int len); 308static void draw_cursor_image(scr_stat *scp); 309static void remove_cursor_image(scr_stat *scp); 310static void move_crsr(scr_stat *scp, int x, int y); 311static void history_to_screen(scr_stat *scp); 312static int history_up_line(scr_stat *scp); 313static int history_down_line(scr_stat *scp); 314static int mask2attr(struct term_stat *term); 315static int save_kbd_state(scr_stat *scp); 316static int update_kbd_state(int state, int mask); 317static int update_kbd_leds(int which); 318static void set_destructive_cursor(scr_stat *scp); 319static void set_mouse_pos(scr_stat *scp); 320static int skip_spc_right(scr_stat *scp, u_short *p); 321static int skip_spc_left(scr_stat *scp, u_short *p); 322static void mouse_cut(scr_stat *scp); 323static void mouse_cut_start(scr_stat *scp); 324static void mouse_cut_end(scr_stat *scp); 325static void mouse_cut_word(scr_stat *scp); 326static void mouse_cut_line(scr_stat *scp); 327static void mouse_cut_extend(scr_stat *scp); 328static void mouse_paste(scr_stat *scp); 329static void draw_mouse_image(scr_stat *scp); 330static void remove_mouse_image(scr_stat *scp); 331static void draw_cutmarking(scr_stat *scp); 332static void remove_cutmarking(scr_stat *scp); 333static void do_bell(scr_stat *scp, int pitch, int duration); 334static timeout_t blink_screen; 335 336#define CDEV_MAJOR 12 337 338#ifdef __i386__ 339 340static cn_probe_t sccnprobe; 341static cn_init_t sccninit; 342static cn_getc_t sccngetc; 343static cn_checkc_t sccncheckc; 344static cn_putc_t sccnputc; 345 346CONS_DRIVER(sc, sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc); 347 348#else /* !__i386__ */ 349 350static cn_getc_t sccngetc; 351static cn_checkc_t sccncheckc; 352static cn_putc_t sccnputc; 353 354struct consdev sc_cons = { 355 NULL, NULL, sccngetc, sccncheckc, sccnputc, 356 NULL, 0, CN_NORMAL, 357}; 358 359#endif /* __i386__ */ 360 361static d_open_t scopen; 362static d_close_t scclose; 363static d_read_t scread; 364static d_write_t scwrite; 365static d_ioctl_t scioctl; 366static d_mmap_t scmmap; 367 368struct cdevsw sc_cdevsw = { 369 scopen, scclose, scread, scwrite, 370 scioctl, nullstop, noreset, scdevtotty, 371 ttpoll, scmmap, nostrategy, "sc", 372 NULL, -1, nodump, nopsize, 373 D_TTY, 374}; 375 376#ifdef __i386__ 377 378#define fillw_io(p, b, c) fillw((p), (void *)(b), (c)) 379 380#endif 381 382#ifdef __alpha__ 383 384static void 385fillw(int pat, void *base, size_t cnt) 386{ 387 u_short *sp = base; 388 while (cnt--) 389 *sp++ = pat; 390} 391 392static void 393fillw_io(int pat, u_int32_t base, size_t cnt) 394{ 395 while (cnt--) { 396 writew(base, pat); 397 base += 2; 398 } 399} 400 401#endif 402 403static void 404draw_cursor_image(scr_stat *scp) 405{ 406 u_short cursor_image; 407 vm_offset_t ptr; 408 u_short prev_image; 409 410 if (ISPIXELSC(scp)) { 411 sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 412 scp->cursor_pos - scp->scr_buf, 1); 413 return; 414 } 415 416 ptr = scp->adp->va_window + 2*(scp->cursor_pos - scp->scr_buf); 417 418 /* do we have a destructive cursor ? */ 419 if (sc_flags & CHAR_CURSOR) { 420 prev_image = scp->cursor_saveunder; 421 cursor_image = readw(ptr) & 0x00ff; 422 if (cursor_image == DEAD_CHAR) 423 cursor_image = prev_image & 0x00ff; 424 cursor_image |= *(scp->cursor_pos) & 0xff00; 425 scp->cursor_saveunder = cursor_image; 426 /* update the cursor bitmap if the char under the cursor has changed */ 427 if (prev_image != cursor_image) 428 set_destructive_cursor(scp); 429 /* modify cursor_image */ 430 if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 431 /* 432 * When the mouse pointer is at the same position as the cursor, 433 * the cursor bitmap needs to be updated even if the char under 434 * the cursor hasn't changed, because the mouse pionter may 435 * have moved by a few dots within the cursor cel. 436 */ 437 if ((prev_image == cursor_image) 438 && (cursor_image != *(scp->cursor_pos))) 439 set_destructive_cursor(scp); 440 cursor_image &= 0xff00; 441 cursor_image |= DEAD_CHAR; 442 } 443 } else { 444 cursor_image = (readw(ptr) & 0x00ff) | (*(scp->cursor_pos) & 0xff00); 445 scp->cursor_saveunder = cursor_image; 446 if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ 447 if ((cursor_image & 0x7000) == 0x7000) { 448 cursor_image &= 0x8fff; 449 if(!(cursor_image & 0x0700)) 450 cursor_image |= 0x0700; 451 } else { 452 cursor_image |= 0x7000; 453 if ((cursor_image & 0x0700) == 0x0700) 454 cursor_image &= 0xf0ff; 455 } 456 } 457 } 458 writew(ptr, cursor_image); 459} 460 461static void 462remove_cursor_image(scr_stat *scp) 463{ 464 if (ISPIXELSC(scp)) 465 sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 466 scp->cursor_oldpos - scp->scr_buf, 0); 467 else 468 writew(scp->adp->va_window + 2*(scp->cursor_oldpos - scp->scr_buf), 469 scp->cursor_saveunder); 470} 471 472static void 473move_crsr(scr_stat *scp, int x, int y) 474{ 475 if (x < 0) 476 x = 0; 477 if (y < 0) 478 y = 0; 479 if (x >= scp->xsize) 480 x = scp->xsize-1; 481 if (y >= scp->ysize) 482 y = scp->ysize-1; 483 scp->xpos = x; 484 scp->ypos = y; 485 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 486} 487 488int 489sc_probe_unit(int unit, int flags) 490{ 491 if (!scvidprobe(unit, flags, FALSE)) { 492 if (bootverbose) 493 printf("sc%d: no video adapter is found.\n", unit); 494 return ENXIO; 495 } 496 497 return ((sckbdprobe(unit, flags, FALSE)) ? 0 : ENXIO); 498} 499 500/* probe video adapters, return TRUE if found */ 501static int 502scvidprobe(int unit, int flags, int cons) 503{ 504 video_adapter_t *adp; 505 506 /* 507 * Access the video adapter driver through the back door! 508 * Video adapter drivers need to be configured before syscons. 509 * However, when syscons is being probed as the low-level console, 510 * they have not been initialized yet. We force them to initialize 511 * themselves here. XXX 512 */ 513 vid_configure(cons ? VIO_PROBE_ONLY : 0); 514 515 /* allocate a frame buffer */ 516 if (adapter < 0) { 517 adapter = vid_allocate("*", -1, (void *)&adapter); 518 if (adapter < 0) 519 return FALSE; 520 } 521 adp = vid_get_adapter(adapter); /* shouldn't fail */ 522 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)) 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); 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 KDSETREPEAT: /* set keyboard repeat & delay rates (new) */ 1570 error = kbd_ioctl(kbd, cmd, data); 1571 if (error == ENOIOCTL) 1572 error = ENODEV; 1573 return error; 1574 1575 case KDSETRAD: /* set keyboard repeat & delay rates (old) */ 1576 if (*(int *)data & ~0x7f) 1577 return EINVAL; 1578 error = kbd_ioctl(kbd, cmd, data); 1579 if (error == ENOIOCTL) 1580 error = ENODEV; 1581 return error; 1582 1583 case KDSKBMODE: /* set keyboard mode */ 1584 switch (*(int *)data) { 1585 case K_XLATE: /* switch to XLT ascii mode */ 1586 case K_RAW: /* switch to RAW scancode mode */ 1587 case K_CODE: /* switch to CODE mode */ 1588 scp->kbd_mode = *(int *)data; 1589 if (scp == cur_console) 1590 kbd_ioctl(kbd, cmd, data); 1591 return 0; 1592 default: 1593 return EINVAL; 1594 } 1595 /* NOT REACHED */ 1596 1597 case KDGKBMODE: /* get keyboard mode */ 1598 *(int *)data = scp->kbd_mode; 1599 return 0; 1600 1601 case KDGKBINFO: 1602 error = kbd_ioctl(kbd, cmd, data); 1603 if (error == ENOIOCTL) 1604 error = ENODEV; 1605 return error; 1606 1607 case KDMKTONE: /* sound the bell */ 1608 if (*(int*)data) 1609 do_bell(scp, (*(int*)data)&0xffff, 1610 (((*(int*)data)>>16)&0xffff)*hz/1000); 1611 else 1612 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1613 return 0; 1614 1615 case KIOCSOUND: /* make tone (*data) hz */ 1616#ifdef __i386__ 1617 if (scp == cur_console) { 1618 if (*(int*)data) { 1619 int pitch = timer_freq / *(int*)data; 1620 1621 /* set command for counter 2, 2 byte write */ 1622 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1623 return EBUSY; 1624 1625 /* set pitch */ 1626 outb(TIMER_CNTR2, pitch); 1627 outb(TIMER_CNTR2, (pitch>>8)); 1628 1629 /* enable counter 2 output to speaker */ 1630 outb(IO_PPI, inb(IO_PPI) | 3); 1631 } 1632 else { 1633 /* disable counter 2 output to speaker */ 1634 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1635 release_timer2(); 1636 } 1637 } 1638#endif /* __i386__ */ 1639 return 0; 1640 1641 case KDGKBTYPE: /* get keyboard type */ 1642 error = kbd_ioctl(kbd, cmd, data); 1643 if (error == ENOIOCTL) { 1644 /* always return something? XXX */ 1645 *(int *)data = 0; 1646 } 1647 return 0; 1648 1649 case KDSETLED: /* set keyboard LED status */ 1650 if (*(int *)data & ~LED_MASK) /* FIXME: LOCK_MASK? */ 1651 return EINVAL; 1652 scp->status &= ~LED_MASK; 1653 scp->status |= *(int *)data; 1654 if (scp == cur_console) 1655 update_kbd_leds(scp->status); 1656 return 0; 1657 1658 case KDGETLED: /* get keyboard LED status */ 1659 if (scp == cur_console) 1660 save_kbd_state(scp); 1661 *(int *)data = scp->status & LED_MASK; 1662 return 0; 1663 1664 case CONS_SETKBD: /* set the new keyboard */ 1665 { 1666 keyboard_t *newkbd; 1667 1668 s = spltty(); 1669 newkbd = kbd_get_keyboard(*(int *)data); 1670 if (newkbd == NULL) { 1671 splx(s); 1672 return EINVAL; 1673 } 1674 error = 0; 1675 if (kbd != newkbd) { 1676 i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit, 1677 (void *)&keyboard, sckbdevent, NULL); 1678 /* i == newkbd->kb_index */ 1679 if (i >= 0) { 1680 if (kbd != NULL) { 1681 save_kbd_state(cur_console); 1682 kbd_release(kbd, (void *)&keyboard); 1683 } 1684 kbd = kbd_get_keyboard(i); /* kbd == newkbd */ 1685 keyboard = i; 1686 kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); 1687 update_kbd_state(cur_console->status, LOCK_MASK); 1688 } else { 1689 error = EPERM; /* XXX */ 1690 } 1691 } 1692 splx(s); 1693 return error; 1694 } 1695 1696 case CONS_RELKBD: /* release the current keyboard */ 1697 s = spltty(); 1698 error = 0; 1699 if (kbd != NULL) { 1700 save_kbd_state(cur_console); 1701 error = kbd_release(kbd, (void *)&keyboard); 1702 if (error == 0) { 1703 kbd = NULL; 1704 keyboard = -1; 1705 } 1706 } 1707 splx(s); 1708 return error; 1709 1710 case GIO_SCRNMAP: /* get output translation table */ 1711 bcopy(&scr_map, data, sizeof(scr_map)); 1712 return 0; 1713 1714 case PIO_SCRNMAP: /* set output translation table */ 1715 bcopy(data, &scr_map, sizeof(scr_map)); 1716 for (i=0; i<sizeof(scr_map); i++) 1717 scr_rmap[scr_map[i]] = i; 1718 return 0; 1719 1720 case GIO_KEYMAP: /* get keyboard translation table */ 1721 case PIO_KEYMAP: /* set keyboard translation table */ 1722 case GIO_DEADKEYMAP: /* get accent key translation table */ 1723 case PIO_DEADKEYMAP: /* set accent key translation table */ 1724 case GETFKEY: /* get function key string */ 1725 case SETFKEY: /* set function key string */ 1726 error = kbd_ioctl(kbd, cmd, data); 1727 if (error == ENOIOCTL) 1728 error = ENODEV; 1729 return error; 1730 1731 case PIO_FONT8x8: /* set 8x8 dot font */ 1732 if (!ISFONTAVAIL(scp->adp->va_flags)) 1733 return ENXIO; 1734 bcopy(data, font_8, 8*256); 1735 fonts_loaded |= FONT_8; 1736 /* 1737 * FONT KLUDGE 1738 * Always use the font page #0. XXX 1739 * Don't load if the current font size is not 8x8. 1740 */ 1741 if (ISTEXTSC(cur_console) && (cur_console->font_size < 14)) 1742 copy_font(cur_console, LOAD, 8, font_8); 1743 return 0; 1744 1745 case GIO_FONT8x8: /* get 8x8 dot font */ 1746 if (!ISFONTAVAIL(scp->adp->va_flags)) 1747 return ENXIO; 1748 if (fonts_loaded & FONT_8) { 1749 bcopy(font_8, data, 8*256); 1750 return 0; 1751 } 1752 else 1753 return ENXIO; 1754 1755 case PIO_FONT8x14: /* set 8x14 dot font */ 1756 if (!ISFONTAVAIL(scp->adp->va_flags)) 1757 return ENXIO; 1758 bcopy(data, font_14, 14*256); 1759 fonts_loaded |= FONT_14; 1760 /* 1761 * FONT KLUDGE 1762 * Always use the font page #0. XXX 1763 * Don't load if the current font size is not 8x14. 1764 */ 1765 if (ISTEXTSC(cur_console) 1766 && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) 1767 copy_font(cur_console, LOAD, 14, font_14); 1768 return 0; 1769 1770 case GIO_FONT8x14: /* get 8x14 dot font */ 1771 if (!ISFONTAVAIL(scp->adp->va_flags)) 1772 return ENXIO; 1773 if (fonts_loaded & FONT_14) { 1774 bcopy(font_14, data, 14*256); 1775 return 0; 1776 } 1777 else 1778 return ENXIO; 1779 1780 case PIO_FONT8x16: /* set 8x16 dot font */ 1781 if (!ISFONTAVAIL(scp->adp->va_flags)) 1782 return ENXIO; 1783 bcopy(data, font_16, 16*256); 1784 fonts_loaded |= FONT_16; 1785 /* 1786 * FONT KLUDGE 1787 * Always use the font page #0. XXX 1788 * Don't load if the current font size is not 8x16. 1789 */ 1790 if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16)) 1791 copy_font(cur_console, LOAD, 16, font_16); 1792 return 0; 1793 1794 case GIO_FONT8x16: /* get 8x16 dot font */ 1795 if (!ISFONTAVAIL(scp->adp->va_flags)) 1796 return ENXIO; 1797 if (fonts_loaded & FONT_16) { 1798 bcopy(font_16, data, 16*256); 1799 return 0; 1800 } 1801 else 1802 return ENXIO; 1803 default: 1804 break; 1805 } 1806 1807 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1808 if (error != ENOIOCTL) 1809 return(error); 1810 error = ttioctl(tp, cmd, data, flag); 1811 if (error != ENOIOCTL) 1812 return(error); 1813 return(ENOTTY); 1814} 1815 1816static void 1817scstart(struct tty *tp) 1818{ 1819 struct clist *rbp; 1820 int s, len; 1821 u_char buf[PCBURST]; 1822 scr_stat *scp = sc_get_scr_stat(tp->t_dev); 1823 1824 if (scp->status & SLKED || blink_in_progress) 1825 return; /* XXX who repeats the call when the above flags are cleared? */ 1826 s = spltty(); 1827 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1828 tp->t_state |= TS_BUSY; 1829 rbp = &tp->t_outq; 1830 while (rbp->c_cc) { 1831 len = q_to_b(rbp, buf, PCBURST); 1832 splx(s); 1833 ansi_put(scp, buf, len); 1834 s = spltty(); 1835 } 1836 tp->t_state &= ~TS_BUSY; 1837 ttwwakeup(tp); 1838 } 1839 splx(s); 1840} 1841 1842static void 1843scmousestart(struct tty *tp) 1844{ 1845 struct clist *rbp; 1846 int s; 1847 u_char buf[PCBURST]; 1848 1849 s = spltty(); 1850 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1851 tp->t_state |= TS_BUSY; 1852 rbp = &tp->t_outq; 1853 while (rbp->c_cc) { 1854 q_to_b(rbp, buf, PCBURST); 1855 } 1856 tp->t_state &= ~TS_BUSY; 1857 ttwwakeup(tp); 1858 } 1859 splx(s); 1860} 1861 1862#if __i386__ 1863 1864/* XXX kludge! */ 1865extern struct isa_driver scdriver; 1866 1867static void 1868sccnprobe(struct consdev *cp) 1869{ 1870#if 0 1871 struct isa_device *dvp; 1872 1873 /* 1874 * Take control if we are the highest priority enabled display device. 1875 */ 1876 dvp = find_display(); 1877 if (dvp == NULL || dvp->id_driver != &scdriver) { 1878 cp->cn_pri = CN_DEAD; 1879 return; 1880 } 1881 1882 if (!scvidprobe(dvp->id_unit, dvp->id_flags, TRUE)) { 1883 cp->cn_pri = CN_DEAD; 1884 return; 1885 } 1886 sckbdprobe(dvp->id_unit, dvp->id_flags, TRUE); 1887#else 1888 if (!scvidprobe(0, 0, TRUE)) { 1889 cp->cn_pri = CN_DEAD; 1890 return; 1891 } 1892 sckbdprobe(0, 0, TRUE); 1893#endif 1894 1895 /* initialize required fields */ 1896 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 1897 cp->cn_pri = CN_INTERNAL; 1898} 1899 1900static void 1901sccninit(struct consdev *cp) 1902{ 1903 scinit(); 1904} 1905 1906#else /* !__i386__ */ 1907 1908extern struct consdev *cn_tab; 1909 1910void 1911sccnattach(void) 1912{ 1913 if (!scvidprobe(0, 0, TRUE) || !sckbdprobe(0, 0, TRUE)) { 1914 return; 1915 } 1916 1917 scinit(); 1918 sc_cons.cn_dev = makedev(CDEV_MAJOR, 0); 1919 cn_tab = &sc_cons; 1920} 1921 1922#endif /* __i386__ */ 1923 1924static void 1925sccnputc(dev_t dev, int c) 1926{ 1927 u_char buf[1]; 1928 scr_stat *scp = console[0]; 1929 term_stat save = scp->term; 1930 u_short *p; 1931 int s; 1932 int i; 1933 1934 if (scp == cur_console && scp->status & SLKED) { 1935 scp->status &= ~SLKED; 1936 update_kbd_state(scp->status, SLKED); 1937 if (cur_console->status & BUFFER_SAVED) { 1938 p = cur_console->history_save; 1939 for (i = 0; i < cur_console->ysize; ++i) { 1940 bcopy(p, cur_console->scr_buf + (cur_console->xsize*i), 1941 cur_console->xsize*sizeof(u_short)); 1942 p += cur_console->xsize; 1943 if (p + cur_console->xsize 1944 > cur_console->history + cur_console->history_size) 1945 p = cur_console->history; 1946 } 1947 cur_console->status &= ~BUFFER_SAVED; 1948 cur_console->history_head = cur_console->history_save; 1949 cur_console->status |= CURSOR_ENABLED; 1950 mark_all(cur_console); 1951 } 1952#if 1 /* XXX */ 1953 scstart(VIRTUAL_TTY(get_scr_num())); 1954#endif 1955 } 1956 1957 scp->term = kernel_console; 1958 current_default = &kernel_default; 1959 if (scp == cur_console && !ISGRAPHSC(scp)) 1960 remove_cursor_image(scp); 1961 buf[0] = c; 1962 ansi_put(scp, buf, 1); 1963 kernel_console = scp->term; 1964 current_default = &user_default; 1965 scp->term = save; 1966 1967 s = spltty(); /* block sckbdevent and scrn_timer */ 1968 sccnupdate(scp); 1969 splx(s); 1970} 1971 1972static int 1973sccngetc(dev_t dev) 1974{ 1975 return sccngetch(0); 1976} 1977 1978static int 1979sccncheckc(dev_t dev) 1980{ 1981 return sccngetch(SCGETC_NONBLOCK); 1982} 1983 1984static int 1985sccngetch(int flags) 1986{ 1987 int cur_mode; 1988 int s = spltty(); /* block sckbdevent and scrn_timer while we poll */ 1989 int c; 1990 1991 /* 1992 * Stop the screen saver and update the screen if necessary. 1993 * What if we have been running in the screen saver code... XXX 1994 */ 1995 sc_touch_scrn_saver(); 1996 sccnupdate(cur_console); 1997 1998 if (kbd == NULL) { 1999 splx(s); 2000 return -1; 2001 } 2002 2003 /* 2004 * Make sure the keyboard is accessible even when the kbd device 2005 * driver is disabled. 2006 */ 2007 kbd_enable(kbd); 2008 2009 /* we shall always use the keyboard in the XLATE mode here */ 2010 cur_mode = cur_console->kbd_mode; 2011 cur_console->kbd_mode = K_XLATE; 2012 kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); 2013 2014 kbd_poll(kbd, TRUE); 2015 c = scgetc(kbd, SCGETC_CN | flags); 2016 kbd_poll(kbd, FALSE); 2017 2018 cur_console->kbd_mode = cur_mode; 2019 kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); 2020 kbd_disable(kbd); 2021 splx(s); 2022 2023 switch (KEYFLAGS(c)) { 2024 case 0: /* normal char */ 2025 return KEYCHAR(c); 2026 case FKEY: /* function key */ 2027 return c; /* XXX */ 2028 case NOKEY: 2029 case ERRKEY: 2030 default: 2031 return -1; 2032 } 2033 /* NOT REACHED */ 2034} 2035 2036static void 2037sccnupdate(scr_stat *scp) 2038{ 2039 /* this is a cut-down version of scrn_timer()... */ 2040 2041 if (font_loading_in_progress) 2042 return; 2043 2044 if (panicstr || shutdown_in_progress) { 2045 sc_touch_scrn_saver(); 2046 } else if (scp != cur_console) { 2047 return; 2048 } 2049 2050 if (!run_scrn_saver) 2051 scrn_idle = FALSE; 2052 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 2053 if (scrn_blanked) 2054 stop_scrn_saver(current_saver); 2055 2056 if (scp != cur_console || blink_in_progress || switch_in_progress) 2057 return; 2058 2059 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 2060 scrn_update(scp, TRUE); 2061} 2062 2063scr_stat 2064*sc_get_scr_stat(dev_t dev) 2065{ 2066 int unit = minor(dev); 2067 2068 if (unit == SC_CONSOLE) 2069 return console[0]; 2070 if (unit >= MAXCONS || unit < 0) 2071 return(NULL); 2072 return console[unit]; 2073} 2074 2075static int 2076get_scr_num() 2077{ 2078 int i = 0; 2079 2080 while ((i < MAXCONS) && (cur_console != console[i])) 2081 i++; 2082 return i < MAXCONS ? i : 0; 2083} 2084 2085static void 2086scrn_timer(void *arg) 2087{ 2088 static int kbd_interval = 0; 2089 struct timeval tv; 2090 scr_stat *scp; 2091 int s; 2092 2093 /* don't do anything when we are touching font */ 2094 if (font_loading_in_progress) { 2095 if (arg) 2096 timeout(scrn_timer, (void *)TRUE, hz / 10); 2097 return; 2098 } 2099 s = spltty(); 2100 2101 if ((kbd == NULL) && (sc_flags & AUTODETECT_KBD)) { 2102 /* try to allocate a keyboard automatically */ 2103 if (++kbd_interval >= 25) { 2104 keyboard = kbd_allocate("*", -1, (void *)&keyboard, 2105 sckbdevent, NULL); 2106 if (keyboard >= 0) { 2107 kbd = kbd_get_keyboard(keyboard); 2108 kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); 2109 update_kbd_state(cur_console->status, LOCK_MASK); 2110 } 2111 kbd_interval = 0; 2112 } 2113 } 2114 2115 /* should we stop the screen saver? */ 2116 getmicrouptime(&tv); 2117 if (panicstr || shutdown_in_progress) 2118 sc_touch_scrn_saver(); 2119 if (run_scrn_saver) { 2120 scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time); 2121 } else { 2122 scrn_time_stamp = tv.tv_sec; 2123 scrn_idle = FALSE; 2124 if (scrn_blank_time > 0) 2125 run_scrn_saver = TRUE; 2126 } 2127 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) 2128 if (scrn_blanked) 2129 stop_scrn_saver(current_saver); 2130 2131 /* should we just return ? */ 2132 if (blink_in_progress || switch_in_progress) { 2133 if (arg) 2134 timeout(scrn_timer, (void *)TRUE, hz / 10); 2135 splx(s); 2136 return; 2137 } 2138 2139 /* Update the screen */ 2140 scp = cur_console; 2141 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 2142 scrn_update(scp, TRUE); 2143 2144 /* should we activate the screen saver? */ 2145 if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) 2146 if (!ISGRAPHSC(scp) || scrn_blanked) 2147 (*current_saver)(TRUE); 2148 2149 if (arg) 2150 timeout(scrn_timer, (void *)TRUE, hz / 25); 2151 splx(s); 2152} 2153 2154static void 2155scrn_update(scr_stat *scp, int show_cursor) 2156{ 2157 /* update screen image */ 2158 if (scp->start <= scp->end) 2159 sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0); 2160 2161 /* we are not to show the cursor and the mouse pointer... */ 2162 if (!show_cursor) { 2163 scp->end = 0; 2164 scp->start = scp->xsize*scp->ysize - 1; 2165 return; 2166 } 2167 2168 /* update "pseudo" mouse pointer image */ 2169 if (scp->status & MOUSE_VISIBLE) { 2170 /* did mouse move since last time ? */ 2171 if (scp->status & MOUSE_MOVED) { 2172 /* do we need to remove old mouse pointer image ? */ 2173 if (scp->mouse_cut_start != NULL || 2174 (scp->mouse_pos-scp->scr_buf) <= scp->start || 2175 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) { 2176 remove_mouse_image(scp); 2177 } 2178 scp->status &= ~MOUSE_MOVED; 2179 draw_mouse_image(scp); 2180 } 2181 else { 2182 /* mouse didn't move, has it been overwritten ? */ 2183 if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start && 2184 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 2185 draw_mouse_image(scp); 2186 } 2187 } 2188 } 2189 2190 /* update cursor image */ 2191 if (scp->status & CURSOR_ENABLED) { 2192 /* did cursor move since last time ? */ 2193 if (scp->cursor_pos != scp->cursor_oldpos) { 2194 /* do we need to remove old cursor image ? */ 2195 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 2196 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 2197 remove_cursor_image(scp); 2198 } 2199 scp->cursor_oldpos = scp->cursor_pos; 2200 draw_cursor_image(scp); 2201 } 2202 else { 2203 /* cursor didn't move, has it been overwritten ? */ 2204 if (scp->cursor_pos - scp->scr_buf >= scp->start && 2205 scp->cursor_pos - scp->scr_buf <= scp->end) { 2206 draw_cursor_image(scp); 2207 } else { 2208 /* if its a blinking cursor, we may have to update it */ 2209 if (sc_flags & BLINK_CURSOR) 2210 draw_cursor_image(scp); 2211 } 2212 } 2213 blinkrate++; 2214 } 2215 2216 if (scp->mouse_cut_start != NULL) 2217 draw_cutmarking(scp); 2218 2219 scp->end = 0; 2220 scp->start = scp->xsize*scp->ysize - 1; 2221} 2222 2223#if NSPLASH > 0 2224 2225static int 2226scsplash_callback(int event) 2227{ 2228 int error; 2229 2230 switch (event) { 2231 case SPLASH_INIT: 2232 scrn_saver_failed = FALSE; 2233 if (add_scrn_saver(scsplash_saver) == 0) { 2234 run_scrn_saver = TRUE; 2235 if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) { 2236 scsplash_stick(TRUE); 2237 (*current_saver)(TRUE); 2238 } 2239 } 2240 return 0; 2241 2242 case SPLASH_TERM: 2243 if (current_saver == scsplash_saver) { 2244 scsplash_stick(FALSE); 2245 error = remove_scrn_saver(scsplash_saver); 2246 if (error) 2247 return error; 2248 } 2249 return 0; 2250 2251 default: 2252 return EINVAL; 2253 } 2254} 2255 2256static void 2257scsplash_saver(int show) 2258{ 2259 static int busy = FALSE; 2260 scr_stat *scp; 2261 2262 if (busy) 2263 return; 2264 busy = TRUE; 2265 2266 scp = cur_console; 2267 if (show) { 2268 if (!scrn_saver_failed) { 2269 if (!scrn_blanked) 2270 set_scrn_saver_mode(scp, -1, NULL, 0); 2271 switch (splash(scp->adp, TRUE)) { 2272 case 0: /* succeeded */ 2273 scrn_blanked = TRUE; 2274 break; 2275 case EAGAIN: /* try later */ 2276 restore_scrn_saver_mode(scp, FALSE); 2277 break; 2278 default: 2279 scrn_saver_failed = TRUE; 2280 scsplash_stick(FALSE); 2281 printf("scsplash_saver(): failed to put up the image\n"); 2282 restore_scrn_saver_mode(scp, TRUE); 2283 break; 2284 } 2285 } 2286 } else if (!sticky_splash) { 2287 if (scrn_blanked && (splash(scp->adp, FALSE) == 0)) { 2288 restore_scrn_saver_mode(scp, TRUE); 2289 scrn_blanked = FALSE; 2290 } 2291 } 2292 busy = FALSE; 2293} 2294 2295static int 2296add_scrn_saver(void (*this_saver)(int)) 2297{ 2298 int error; 2299 2300 if (current_saver != none_saver) { 2301 error = remove_scrn_saver(current_saver); 2302 if (error) 2303 return error; 2304 } 2305 2306 run_scrn_saver = FALSE; 2307 saver_mode = CONS_LKM_SAVER; 2308 current_saver = this_saver; 2309 return 0; 2310} 2311 2312static int 2313remove_scrn_saver(void (*this_saver)(int)) 2314{ 2315 if (current_saver != this_saver) 2316 return EINVAL; 2317 2318 /* 2319 * In order to prevent `current_saver' from being called by 2320 * the timeout routine `scrn_timer()' while we manipulate 2321 * the saver list, we shall set `current_saver' to `none_saver' 2322 * before stopping the current saver, rather than blocking by `splXX()'. 2323 */ 2324 current_saver = none_saver; 2325 if (scrn_blanked) 2326 stop_scrn_saver(this_saver); 2327 2328 return (scrn_blanked ? EBUSY : 0); 2329} 2330 2331static int 2332set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border) 2333{ 2334 int s; 2335 2336 /* assert(scp == cur_console) */ 2337 s = spltty(); 2338 scp->splash_save_mode = scp->mode; 2339 scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE); 2340 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE); 2341 scp->status |= (UNKNOWN_MODE | SAVER_RUNNING); 2342 splx(s); 2343 if (mode < 0) 2344 return 0; 2345 scp->mode = mode; 2346 if (set_mode(scp) == 0) { 2347 if (scp->adp->va_info.vi_flags & V_INFO_GRAPHICS) 2348 scp->status |= GRAPHICS_MODE; 2349 if (pal != NULL) 2350 load_palette(scp->adp, pal); 2351 set_border(scp, border); 2352 return 0; 2353 } else { 2354 s = spltty(); 2355 scp->mode = scp->splash_save_mode; 2356 scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); 2357 scp->status |= scp->splash_save_status; 2358 splx(s); 2359 return 1; 2360 } 2361} 2362 2363static int 2364restore_scrn_saver_mode(scr_stat *scp, int changemode) 2365{ 2366 int mode; 2367 int status; 2368 int s; 2369 2370 /* assert(scp == cur_console) */ 2371 s = spltty(); 2372 mode = scp->mode; 2373 status = scp->status; 2374 scp->mode = scp->splash_save_mode; 2375 scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); 2376 scp->status |= scp->splash_save_status; 2377 if (!changemode) { 2378 splx(s); 2379 return 0; 2380 } 2381 if (set_mode(scp) == 0) { 2382 load_palette(scp->adp, palette); 2383 splx(s); 2384 return 0; 2385 } else { 2386 scp->mode = mode; 2387 scp->status = status; 2388 splx(s); 2389 return 1; 2390 } 2391} 2392 2393static void 2394stop_scrn_saver(void (*saver)(int)) 2395{ 2396 (*saver)(FALSE); 2397 run_scrn_saver = FALSE; 2398 /* the screen saver may have chosen not to stop after all... */ 2399 if (scrn_blanked) 2400 return; 2401 2402 mark_all(cur_console); 2403 if (delayed_next_scr) 2404 switch_scr(cur_console, delayed_next_scr - 1); 2405 wakeup((caddr_t)&scrn_blanked); 2406} 2407 2408static int 2409wait_scrn_saver_stop(void) 2410{ 2411 int error = 0; 2412 2413 while (scrn_blanked) { 2414 run_scrn_saver = FALSE; 2415 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); 2416 run_scrn_saver = FALSE; 2417 if (error != ERESTART) 2418 break; 2419 } 2420 return error; 2421} 2422 2423#endif /* NSPLASH */ 2424 2425void 2426sc_touch_scrn_saver(void) 2427{ 2428 scsplash_stick(FALSE); 2429 run_scrn_saver = FALSE; 2430} 2431 2432void 2433sc_clear_screen(scr_stat *scp) 2434{ 2435 move_crsr(scp, 0, 0); 2436 scp->cursor_oldpos = scp->cursor_pos; 2437 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2438 scp->xsize * scp->ysize); 2439 mark_all(scp); 2440 remove_cutmarking(scp); 2441} 2442 2443static int 2444switch_scr(scr_stat *scp, u_int next_scr) 2445{ 2446 /* delay switch if actively updating screen */ 2447 if (scrn_blanked || write_in_progress || blink_in_progress) { 2448 delayed_next_scr = next_scr+1; 2449 sc_touch_scrn_saver(); 2450 return 0; 2451 } 2452 2453 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 2454 switch_in_progress = FALSE; 2455 2456 if (next_scr >= MAXCONS || switch_in_progress || 2457 (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { 2458 do_bell(scp, BELL_PITCH, BELL_DURATION); 2459 return EINVAL; 2460 } 2461 2462 /* is the wanted virtual console open ? */ 2463 if (next_scr) { 2464 struct tty *tp = VIRTUAL_TTY(next_scr); 2465 if (!(tp->t_state & TS_ISOPEN)) { 2466 do_bell(scp, BELL_PITCH, BELL_DURATION); 2467 return EINVAL; 2468 } 2469 } 2470 2471 switch_in_progress = TRUE; 2472 old_scp = cur_console; 2473 new_scp = console[next_scr]; 2474 wakeup((caddr_t)&new_scp->smode); 2475 if (new_scp == old_scp) { 2476 switch_in_progress = FALSE; 2477 delayed_next_scr = FALSE; 2478 return 0; 2479 } 2480 2481 /* has controlling process died? */ 2482 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 2483 old_scp->smode.mode = VT_AUTO; 2484 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 2485 new_scp->smode.mode = VT_AUTO; 2486 2487 /* check the modes and switch appropriately */ 2488 if (old_scp->smode.mode == VT_PROCESS) { 2489 old_scp->status |= SWITCH_WAIT_REL; 2490 psignal(old_scp->proc, old_scp->smode.relsig); 2491 } 2492 else { 2493 exchange_scr(); 2494 if (new_scp->smode.mode == VT_PROCESS) { 2495 new_scp->status |= SWITCH_WAIT_ACQ; 2496 psignal(new_scp->proc, new_scp->smode.acqsig); 2497 } 2498 else 2499 switch_in_progress = FALSE; 2500 } 2501 return 0; 2502} 2503 2504static void 2505exchange_scr(void) 2506{ 2507 /* save the current state of video and keyboard */ 2508 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 2509 if (old_scp->kbd_mode == K_XLATE) 2510 save_kbd_state(old_scp); 2511 2512 /* set up the video for the new screen */ 2513 cur_console = new_scp; 2514 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) 2515 set_mode(new_scp); 2516 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 2517 if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) 2518 set_destructive_cursor(new_scp); 2519 if (ISGRAPHSC(old_scp)) 2520 load_palette(new_scp->adp, palette); 2521 set_border(new_scp, new_scp->border); 2522 2523 /* set up the keyboard for the new screen */ 2524 if (old_scp->kbd_mode != new_scp->kbd_mode) 2525 kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&new_scp->kbd_mode); 2526 update_kbd_state(new_scp->status, LOCK_MASK); 2527 2528 delayed_next_scr = FALSE; 2529 mark_all(new_scp); 2530} 2531 2532static void 2533scan_esc(scr_stat *scp, u_char c) 2534{ 2535 static u_char ansi_col[16] = 2536 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2537 int i, n; 2538 u_short *src, *dst, count; 2539 2540 if (scp->term.esc == 1) { /* seen ESC */ 2541 switch (c) { 2542 2543 case '7': /* Save cursor position */ 2544 scp->saved_xpos = scp->xpos; 2545 scp->saved_ypos = scp->ypos; 2546 break; 2547 2548 case '8': /* Restore saved cursor position */ 2549 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2550 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2551 break; 2552 2553 case '[': /* Start ESC [ sequence */ 2554 scp->term.esc = 2; 2555 scp->term.last_param = -1; 2556 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2557 scp->term.param[i] = 1; 2558 scp->term.num_param = 0; 2559 return; 2560 2561 case 'M': /* Move cursor up 1 line, scroll if at top */ 2562 if (scp->ypos > 0) 2563 move_crsr(scp, scp->xpos, scp->ypos - 1); 2564 else { 2565 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 2566 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 2567 fillw(scp->term.cur_color | scr_map[0x20], 2568 scp->scr_buf, scp->xsize); 2569 mark_all(scp); 2570 } 2571 break; 2572#if notyet 2573 case 'Q': 2574 scp->term.esc = 4; 2575 return; 2576#endif 2577 case 'c': /* Clear screen & home */ 2578 sc_clear_screen(scp); 2579 break; 2580 2581 case '(': /* iso-2022: designate 94 character set to G0 */ 2582 scp->term.esc = 5; 2583 return; 2584 } 2585 } 2586 else if (scp->term.esc == 2) { /* seen ESC [ */ 2587 if (c >= '0' && c <= '9') { 2588 if (scp->term.num_param < MAX_ESC_PAR) { 2589 if (scp->term.last_param != scp->term.num_param) { 2590 scp->term.last_param = scp->term.num_param; 2591 scp->term.param[scp->term.num_param] = 0; 2592 } 2593 else 2594 scp->term.param[scp->term.num_param] *= 10; 2595 scp->term.param[scp->term.num_param] += c - '0'; 2596 return; 2597 } 2598 } 2599 scp->term.num_param = scp->term.last_param + 1; 2600 switch (c) { 2601 2602 case ';': 2603 if (scp->term.num_param < MAX_ESC_PAR) 2604 return; 2605 break; 2606 2607 case '=': 2608 scp->term.esc = 3; 2609 scp->term.last_param = -1; 2610 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2611 scp->term.param[i] = 1; 2612 scp->term.num_param = 0; 2613 return; 2614 2615 case 'A': /* up n rows */ 2616 n = scp->term.param[0]; if (n < 1) n = 1; 2617 move_crsr(scp, scp->xpos, scp->ypos - n); 2618 break; 2619 2620 case 'B': /* down n rows */ 2621 n = scp->term.param[0]; if (n < 1) n = 1; 2622 move_crsr(scp, scp->xpos, scp->ypos + n); 2623 break; 2624 2625 case 'C': /* right n columns */ 2626 n = scp->term.param[0]; if (n < 1) n = 1; 2627 move_crsr(scp, scp->xpos + n, scp->ypos); 2628 break; 2629 2630 case 'D': /* left n columns */ 2631 n = scp->term.param[0]; if (n < 1) n = 1; 2632 move_crsr(scp, scp->xpos - n, scp->ypos); 2633 break; 2634 2635 case 'E': /* cursor to start of line n lines down */ 2636 n = scp->term.param[0]; if (n < 1) n = 1; 2637 move_crsr(scp, 0, scp->ypos + n); 2638 break; 2639 2640 case 'F': /* cursor to start of line n lines up */ 2641 n = scp->term.param[0]; if (n < 1) n = 1; 2642 move_crsr(scp, 0, scp->ypos - n); 2643 break; 2644 2645 case 'f': /* Cursor move */ 2646 case 'H': 2647 if (scp->term.num_param == 0) 2648 move_crsr(scp, 0, 0); 2649 else if (scp->term.num_param == 2) 2650 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2651 break; 2652 2653 case 'J': /* Clear all or part of display */ 2654 if (scp->term.num_param == 0) 2655 n = 0; 2656 else 2657 n = scp->term.param[0]; 2658 switch (n) { 2659 case 0: /* clear form cursor to end of display */ 2660 fillw(scp->term.cur_color | scr_map[0x20], 2661 scp->cursor_pos, 2662 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2663 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2664 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2665 remove_cutmarking(scp); 2666 break; 2667 case 1: /* clear from beginning of display to cursor */ 2668 fillw(scp->term.cur_color | scr_map[0x20], 2669 scp->scr_buf, 2670 scp->cursor_pos - scp->scr_buf); 2671 mark_for_update(scp, 0); 2672 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2673 remove_cutmarking(scp); 2674 break; 2675 case 2: /* clear entire display */ 2676 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2677 scp->xsize * scp->ysize); 2678 mark_all(scp); 2679 remove_cutmarking(scp); 2680 break; 2681 } 2682 break; 2683 2684 case 'K': /* Clear all or part of line */ 2685 if (scp->term.num_param == 0) 2686 n = 0; 2687 else 2688 n = scp->term.param[0]; 2689 switch (n) { 2690 case 0: /* clear form cursor to end of line */ 2691 fillw(scp->term.cur_color | scr_map[0x20], 2692 scp->cursor_pos, 2693 scp->xsize - scp->xpos); 2694 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2695 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2696 scp->xsize - 1 - scp->xpos); 2697 break; 2698 case 1: /* clear from beginning of line to cursor */ 2699 fillw(scp->term.cur_color | scr_map[0x20], 2700 scp->cursor_pos - scp->xpos, 2701 scp->xpos + 1); 2702 mark_for_update(scp, scp->ypos * scp->xsize); 2703 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2704 break; 2705 case 2: /* clear entire line */ 2706 fillw(scp->term.cur_color | scr_map[0x20], 2707 scp->cursor_pos - scp->xpos, 2708 scp->xsize); 2709 mark_for_update(scp, scp->ypos * scp->xsize); 2710 mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); 2711 break; 2712 } 2713 break; 2714 2715 case 'L': /* Insert n lines */ 2716 n = scp->term.param[0]; if (n < 1) n = 1; 2717 if (n > scp->ysize - scp->ypos) 2718 n = scp->ysize - scp->ypos; 2719 src = scp->scr_buf + scp->ypos * scp->xsize; 2720 dst = src + n * scp->xsize; 2721 count = scp->ysize - (scp->ypos + n); 2722 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2723 fillw(scp->term.cur_color | scr_map[0x20], src, 2724 n * scp->xsize); 2725 mark_for_update(scp, scp->ypos * scp->xsize); 2726 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2727 break; 2728 2729 case 'M': /* Delete n lines */ 2730 n = scp->term.param[0]; if (n < 1) n = 1; 2731 if (n > scp->ysize - scp->ypos) 2732 n = scp->ysize - scp->ypos; 2733 dst = scp->scr_buf + scp->ypos * scp->xsize; 2734 src = dst + n * scp->xsize; 2735 count = scp->ysize - (scp->ypos + n); 2736 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2737 src = dst + count * scp->xsize; 2738 fillw(scp->term.cur_color | scr_map[0x20], src, 2739 n * scp->xsize); 2740 mark_for_update(scp, scp->ypos * scp->xsize); 2741 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2742 break; 2743 2744 case 'P': /* Delete n chars */ 2745 n = scp->term.param[0]; if (n < 1) n = 1; 2746 if (n > scp->xsize - scp->xpos) 2747 n = scp->xsize - scp->xpos; 2748 dst = scp->cursor_pos; 2749 src = dst + n; 2750 count = scp->xsize - (scp->xpos + n); 2751 bcopy(src, dst, count * sizeof(u_short)); 2752 src = dst + count; 2753 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2754 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2755 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2756 break; 2757 2758 case '@': /* Insert n chars */ 2759 n = scp->term.param[0]; if (n < 1) n = 1; 2760 if (n > scp->xsize - scp->xpos) 2761 n = scp->xsize - scp->xpos; 2762 src = scp->cursor_pos; 2763 dst = src + n; 2764 count = scp->xsize - (scp->xpos + n); 2765 bcopy(src, dst, count * sizeof(u_short)); 2766 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2767 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2768 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); 2769 break; 2770 2771 case 'S': /* scroll up n lines */ 2772 n = scp->term.param[0]; if (n < 1) n = 1; 2773 if (n > scp->ysize) 2774 n = scp->ysize; 2775 bcopy(scp->scr_buf + (scp->xsize * n), 2776 scp->scr_buf, 2777 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2778 fillw(scp->term.cur_color | scr_map[0x20], 2779 scp->scr_buf + scp->xsize * (scp->ysize - n), 2780 scp->xsize * n); 2781 mark_all(scp); 2782 break; 2783 2784 case 'T': /* scroll down n lines */ 2785 n = scp->term.param[0]; if (n < 1) n = 1; 2786 if (n > scp->ysize) 2787 n = scp->ysize; 2788 bcopy(scp->scr_buf, 2789 scp->scr_buf + (scp->xsize * n), 2790 scp->xsize * (scp->ysize - n) * 2791 sizeof(u_short)); 2792 fillw(scp->term.cur_color | scr_map[0x20], 2793 scp->scr_buf, scp->xsize * n); 2794 mark_all(scp); 2795 break; 2796 2797 case 'X': /* erase n characters in line */ 2798 n = scp->term.param[0]; if (n < 1) n = 1; 2799 if (n > scp->xsize - scp->xpos) 2800 n = scp->xsize - scp->xpos; 2801 fillw(scp->term.cur_color | scr_map[0x20], 2802 scp->cursor_pos, n); 2803 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2804 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1); 2805 break; 2806 2807 case 'Z': /* move n tabs backwards */ 2808 n = scp->term.param[0]; if (n < 1) n = 1; 2809 if ((i = scp->xpos & 0xf8) == scp->xpos) 2810 i -= 8*n; 2811 else 2812 i -= 8*(n-1); 2813 if (i < 0) 2814 i = 0; 2815 move_crsr(scp, i, scp->ypos); 2816 break; 2817 2818 case '`': /* move cursor to column n */ 2819 n = scp->term.param[0]; if (n < 1) n = 1; 2820 move_crsr(scp, n - 1, scp->ypos); 2821 break; 2822 2823 case 'a': /* move cursor n columns to the right */ 2824 n = scp->term.param[0]; if (n < 1) n = 1; 2825 move_crsr(scp, scp->xpos + n, scp->ypos); 2826 break; 2827 2828 case 'd': /* move cursor to row n */ 2829 n = scp->term.param[0]; if (n < 1) n = 1; 2830 move_crsr(scp, scp->xpos, n - 1); 2831 break; 2832 2833 case 'e': /* move cursor n rows down */ 2834 n = scp->term.param[0]; if (n < 1) n = 1; 2835 move_crsr(scp, scp->xpos, scp->ypos + n); 2836 break; 2837 2838 case 'm': /* change attribute */ 2839 if (scp->term.num_param == 0) { 2840 scp->term.attr_mask = NORMAL_ATTR; 2841 scp->term.cur_attr = 2842 scp->term.cur_color = scp->term.std_color; 2843 break; 2844 } 2845 for (i = 0; i < scp->term.num_param; i++) { 2846 switch (n = scp->term.param[i]) { 2847 case 0: /* back to normal */ 2848 scp->term.attr_mask = NORMAL_ATTR; 2849 scp->term.cur_attr = 2850 scp->term.cur_color = scp->term.std_color; 2851 break; 2852 case 1: /* bold */ 2853 scp->term.attr_mask |= BOLD_ATTR; 2854 scp->term.cur_attr = mask2attr(&scp->term); 2855 break; 2856 case 4: /* underline */ 2857 scp->term.attr_mask |= UNDERLINE_ATTR; 2858 scp->term.cur_attr = mask2attr(&scp->term); 2859 break; 2860 case 5: /* blink */ 2861 scp->term.attr_mask |= BLINK_ATTR; 2862 scp->term.cur_attr = mask2attr(&scp->term); 2863 break; 2864 case 7: /* reverse video */ 2865 scp->term.attr_mask |= REVERSE_ATTR; 2866 scp->term.cur_attr = mask2attr(&scp->term); 2867 break; 2868 case 30: case 31: /* set fg color */ 2869 case 32: case 33: case 34: 2870 case 35: case 36: case 37: 2871 scp->term.attr_mask |= FOREGROUND_CHANGED; 2872 scp->term.cur_color = 2873 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2874 scp->term.cur_attr = mask2attr(&scp->term); 2875 break; 2876 case 40: case 41: /* set bg color */ 2877 case 42: case 43: case 44: 2878 case 45: case 46: case 47: 2879 scp->term.attr_mask |= BACKGROUND_CHANGED; 2880 scp->term.cur_color = 2881 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2882 scp->term.cur_attr = mask2attr(&scp->term); 2883 break; 2884 } 2885 } 2886 break; 2887 2888 case 's': /* Save cursor position */ 2889 scp->saved_xpos = scp->xpos; 2890 scp->saved_ypos = scp->ypos; 2891 break; 2892 2893 case 'u': /* Restore saved cursor position */ 2894 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2895 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2896 break; 2897 2898 case 'x': 2899 if (scp->term.num_param == 0) 2900 n = 0; 2901 else 2902 n = scp->term.param[0]; 2903 switch (n) { 2904 case 0: /* reset attributes */ 2905 scp->term.attr_mask = NORMAL_ATTR; 2906 scp->term.cur_attr = 2907 scp->term.cur_color = scp->term.std_color = 2908 current_default->std_color; 2909 scp->term.rev_color = current_default->rev_color; 2910 break; 2911 case 1: /* set ansi background */ 2912 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2913 scp->term.cur_color = scp->term.std_color = 2914 (scp->term.std_color & 0x0F00) | 2915 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2916 scp->term.cur_attr = mask2attr(&scp->term); 2917 break; 2918 case 2: /* set ansi foreground */ 2919 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2920 scp->term.cur_color = scp->term.std_color = 2921 (scp->term.std_color & 0xF000) | 2922 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2923 scp->term.cur_attr = mask2attr(&scp->term); 2924 break; 2925 case 3: /* set ansi attribute directly */ 2926 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2927 scp->term.cur_color = scp->term.std_color = 2928 (scp->term.param[1]&0xFF)<<8; 2929 scp->term.cur_attr = mask2attr(&scp->term); 2930 break; 2931 case 5: /* set ansi reverse video background */ 2932 scp->term.rev_color = 2933 (scp->term.rev_color & 0x0F00) | 2934 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2935 scp->term.cur_attr = mask2attr(&scp->term); 2936 break; 2937 case 6: /* set ansi reverse video foreground */ 2938 scp->term.rev_color = 2939 (scp->term.rev_color & 0xF000) | 2940 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2941 scp->term.cur_attr = mask2attr(&scp->term); 2942 break; 2943 case 7: /* set ansi reverse video directly */ 2944 scp->term.rev_color = 2945 (scp->term.param[1]&0xFF)<<8; 2946 scp->term.cur_attr = mask2attr(&scp->term); 2947 break; 2948 } 2949 break; 2950 2951 case 'z': /* switch to (virtual) console n */ 2952 if (scp->term.num_param == 1) 2953 switch_scr(scp, scp->term.param[0]); 2954 break; 2955 } 2956 } 2957 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2958 if (c >= '0' && c <= '9') { 2959 if (scp->term.num_param < MAX_ESC_PAR) { 2960 if (scp->term.last_param != scp->term.num_param) { 2961 scp->term.last_param = scp->term.num_param; 2962 scp->term.param[scp->term.num_param] = 0; 2963 } 2964 else 2965 scp->term.param[scp->term.num_param] *= 10; 2966 scp->term.param[scp->term.num_param] += c - '0'; 2967 return; 2968 } 2969 } 2970 scp->term.num_param = scp->term.last_param + 1; 2971 switch (c) { 2972 2973 case ';': 2974 if (scp->term.num_param < MAX_ESC_PAR) 2975 return; 2976 break; 2977 2978 case 'A': /* set display border color */ 2979 if (scp->term.num_param == 1) { 2980 scp->border=scp->term.param[0] & 0xff; 2981 if (scp == cur_console) 2982 set_border(cur_console, scp->border); 2983 } 2984 break; 2985 2986 case 'B': /* set bell pitch and duration */ 2987 if (scp->term.num_param == 2) { 2988 scp->bell_pitch = scp->term.param[0]; 2989 scp->bell_duration = scp->term.param[1]; 2990 } 2991 break; 2992 2993 case 'C': /* set cursor type & shape */ 2994 if (scp->term.num_param == 1) { 2995 if (scp->term.param[0] & 0x01) 2996 sc_flags |= BLINK_CURSOR; 2997 else 2998 sc_flags &= ~BLINK_CURSOR; 2999 if ((scp->term.param[0] & 0x02) 3000 && ISFONTAVAIL(scp->adp->va_flags)) 3001 sc_flags |= CHAR_CURSOR; 3002 else 3003 sc_flags &= ~CHAR_CURSOR; 3004 } 3005 else if (scp->term.num_param == 2) { 3006 scp->cursor_start = scp->term.param[0] & 0x1F; 3007 scp->cursor_end = scp->term.param[1] & 0x1F; 3008 } 3009 /* 3010 * The cursor shape is global property; all virtual consoles 3011 * are affected. Update the cursor in the current console... 3012 */ 3013 if (!ISGRAPHSC(cur_console)) { 3014 i = spltty(); 3015 remove_cursor_image(cur_console); 3016 if (sc_flags & CHAR_CURSOR) 3017 set_destructive_cursor(cur_console); 3018 draw_cursor_image(cur_console); 3019 splx(i); 3020 } 3021 break; 3022 3023 case 'F': /* set ansi foreground */ 3024 if (scp->term.num_param == 1) { 3025 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 3026 scp->term.cur_color = scp->term.std_color = 3027 (scp->term.std_color & 0xF000) 3028 | ((scp->term.param[0] & 0x0F) << 8); 3029 scp->term.cur_attr = mask2attr(&scp->term); 3030 } 3031 break; 3032 3033 case 'G': /* set ansi background */ 3034 if (scp->term.num_param == 1) { 3035 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 3036 scp->term.cur_color = scp->term.std_color = 3037 (scp->term.std_color & 0x0F00) 3038 | ((scp->term.param[0] & 0x0F) << 12); 3039 scp->term.cur_attr = mask2attr(&scp->term); 3040 } 3041 break; 3042 3043 case 'H': /* set ansi reverse video foreground */ 3044 if (scp->term.num_param == 1) { 3045 scp->term.rev_color = 3046 (scp->term.rev_color & 0xF000) 3047 | ((scp->term.param[0] & 0x0F) << 8); 3048 scp->term.cur_attr = mask2attr(&scp->term); 3049 } 3050 break; 3051 3052 case 'I': /* set ansi reverse video background */ 3053 if (scp->term.num_param == 1) { 3054 scp->term.rev_color = 3055 (scp->term.rev_color & 0x0F00) 3056 | ((scp->term.param[0] & 0x0F) << 12); 3057 scp->term.cur_attr = mask2attr(&scp->term); 3058 } 3059 break; 3060 } 3061 } 3062#if notyet 3063 else if (scp->term.esc == 4) { /* seen ESC Q */ 3064 /* to be filled */ 3065 } 3066#endif 3067 else if (scp->term.esc == 5) { /* seen ESC ( */ 3068 switch (c) { 3069 case 'B': /* iso-2022: desginate ASCII into G0 */ 3070 break; 3071 /* other items to be filled */ 3072 default: 3073 break; 3074 } 3075 } 3076 scp->term.esc = 0; 3077} 3078 3079static void 3080ansi_put(scr_stat *scp, u_char *buf, int len) 3081{ 3082 u_char *ptr = buf; 3083 3084 /* make screensaver happy */ 3085 if (!sticky_splash && scp == cur_console) 3086 run_scrn_saver = FALSE; 3087 3088 write_in_progress++; 3089outloop: 3090 if (scp->term.esc) { 3091 scan_esc(scp, *ptr++); 3092 len--; 3093 } 3094 else if (PRINTABLE(*ptr)) { /* Print only printables */ 3095 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 3096 u_short cur_attr = scp->term.cur_attr; 3097 u_short *cursor_pos = scp->cursor_pos; 3098 do { 3099 /* 3100 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 3101 * pointers in the following to volatile should have no effect, 3102 * but in fact speeds up this inner loop from 26 to 18 cycles 3103 * (+ cache misses) on i486's. 3104 */ 3105#define UCVP(ucp) ((u_char volatile *)(ucp)) 3106 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 3107 ptr++; 3108 cnt--; 3109 } while (cnt && PRINTABLE(*ptr)); 3110 len -= (cursor_pos - scp->cursor_pos); 3111 scp->xpos += (cursor_pos - scp->cursor_pos); 3112 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3113 mark_for_update(scp, cursor_pos - scp->scr_buf); 3114 scp->cursor_pos = cursor_pos; 3115 if (scp->xpos >= scp->xsize) { 3116 scp->xpos = 0; 3117 scp->ypos++; 3118 } 3119 } 3120 else { 3121 switch(*ptr) { 3122 case 0x07: 3123 do_bell(scp, scp->bell_pitch, scp->bell_duration); 3124 break; 3125 3126 case 0x08: /* non-destructive backspace */ 3127 if (scp->cursor_pos > scp->scr_buf) { 3128 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3129 scp->cursor_pos--; 3130 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3131 if (scp->xpos > 0) 3132 scp->xpos--; 3133 else { 3134 scp->xpos += scp->xsize - 1; 3135 scp->ypos--; 3136 } 3137 } 3138 break; 3139 3140 case 0x09: /* non-destructive tab */ 3141 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3142 scp->cursor_pos += (8 - scp->xpos % 8u); 3143 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3144 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 3145 scp->xpos = 0; 3146 scp->ypos++; 3147 } 3148 break; 3149 3150 case 0x0a: /* newline, same pos */ 3151 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3152 scp->cursor_pos += scp->xsize; 3153 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3154 scp->ypos++; 3155 break; 3156 3157 case 0x0c: /* form feed, clears screen */ 3158 sc_clear_screen(scp); 3159 break; 3160 3161 case 0x0d: /* return, return to pos 0 */ 3162 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3163 scp->cursor_pos -= scp->xpos; 3164 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3165 scp->xpos = 0; 3166 break; 3167 3168 case 0x1b: /* start escape sequence */ 3169 scp->term.esc = 1; 3170 scp->term.num_param = 0; 3171 break; 3172 } 3173 ptr++; len--; 3174 } 3175 /* do we have to scroll ?? */ 3176 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 3177 remove_cutmarking(scp); 3178 if (scp->history != NULL) { 3179 bcopy(scp->scr_buf, scp->history_head, 3180 scp->xsize * sizeof(u_short)); 3181 scp->history_head += scp->xsize; 3182 if (scp->history_head + scp->xsize > 3183 scp->history + scp->history_size) 3184 scp->history_head = scp->history; 3185 } 3186 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 3187 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 3188 fillw(scp->term.cur_color | scr_map[0x20], 3189 scp->scr_buf + scp->xsize * (scp->ysize - 1), 3190 scp->xsize); 3191 scp->cursor_pos -= scp->xsize; 3192 scp->ypos--; 3193 mark_all(scp); 3194 } 3195 if (len) 3196 goto outloop; 3197 write_in_progress--; 3198 if (delayed_next_scr) 3199 switch_scr(scp, delayed_next_scr - 1); 3200} 3201 3202static void 3203scinit(void) 3204{ 3205 video_adapter_t *adp; 3206 int col; 3207 int row; 3208 u_int i; 3209 3210 if (init_done != COLD) 3211 return; 3212 init_done = WARM; 3213 3214 get_bios_values(); 3215 3216 /* extract the hardware cursor location and hide the cursor for now */ 3217 adp = vid_get_adapter(adapter); 3218 (*vidsw[adapter]->read_hw_cursor)(adp, &col, &row); 3219 (*vidsw[adapter]->set_hw_cursor)(adp, -1, -1); 3220 3221 /* set up the first console */ 3222 current_default = &user_default; 3223 console[0] = &main_console; 3224 init_scp(console[0]); 3225 cur_console = console[0]; 3226 3227 /* copy screen to temporary buffer */ 3228 if (ISTEXTSC(console[0])) 3229 bcopy_fromio(console[0]->adp->va_window, sc_buffer, 3230 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 3231 3232 console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos 3233 = sc_buffer; 3234 if (col >= console[0]->xsize) 3235 col = 0; 3236 if (row >= console[0]->ysize) 3237 row = console[0]->ysize - 1; 3238 console[0]->xpos = col; 3239 console[0]->ypos = row; 3240 console[0]->cursor_pos = console[0]->cursor_oldpos = 3241 sc_buffer + row*console[0]->xsize + col; 3242 console[0]->cursor_saveunder = *console[0]->cursor_pos; 3243 for (i=1; i<MAXCONS; i++) 3244 console[i] = NULL; 3245 kernel_console.esc = 0; 3246 kernel_console.attr_mask = NORMAL_ATTR; 3247 kernel_console.cur_attr = 3248 kernel_console.cur_color = kernel_console.std_color = 3249 kernel_default.std_color; 3250 kernel_console.rev_color = kernel_default.rev_color; 3251 3252 /* initialize mapscrn arrays to a one to one map */ 3253 for (i=0; i<sizeof(scr_map); i++) { 3254 scr_map[i] = scr_rmap[i] = i; 3255 } 3256 3257 /* Save font and palette */ 3258 if (ISFONTAVAIL(cur_console->adp->va_flags)) { 3259 if (fonts_loaded & FONT_16) { 3260 copy_font(cur_console, LOAD, 16, font_16); 3261 } else { 3262 copy_font(cur_console, SAVE, 16, font_16); 3263 fonts_loaded = FONT_16; 3264 set_destructive_cursor(cur_console); 3265 } 3266 /* 3267 * FONT KLUDGE 3268 * Always use the font page #0. XXX 3269 */ 3270 (*vidsw[cur_console->ad]->show_font)(cur_console->adp, 0); 3271 } 3272 save_palette(cur_console->adp, palette); 3273 3274#if NSPLASH > 0 3275 /* we are ready to put up the splash image! */ 3276 splash_init(cur_console->adp, scsplash_callback); 3277#endif 3278} 3279 3280static void 3281scshutdown(int howto, void *arg) 3282{ 3283 sc_touch_scrn_saver(); 3284 if (!cold && cur_console->smode.mode == VT_AUTO 3285 && console[0]->smode.mode == VT_AUTO) 3286 switch_scr(cur_console, 0); 3287 shutdown_in_progress = TRUE; 3288} 3289 3290int 3291sc_clean_up(scr_stat *scp) 3292{ 3293 int error; 3294 3295 sc_touch_scrn_saver(); 3296 if ((error = wait_scrn_saver_stop())) 3297 return error; 3298 scp->status &= ~MOUSE_VISIBLE; 3299 remove_cutmarking(scp); 3300 return 0; 3301} 3302 3303void 3304sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) 3305{ 3306 if (scp->scr_buf) 3307 free(scp->scr_buf, M_DEVBUF); 3308 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 3309 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3310 3311 if (clear) { 3312 /* clear the screen and move the text cursor to the top-left position */ 3313 sc_clear_screen(scp); 3314 } else { 3315 /* retain the current cursor position, but adjust pointers */ 3316 move_crsr(scp, scp->xpos, scp->ypos); 3317 scp->cursor_oldpos = scp->cursor_pos; 3318 } 3319 3320 /* move the mouse cursor at the center of the screen */ 3321 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); 3322} 3323 3324void 3325sc_alloc_cut_buffer(scr_stat *scp, int wait) 3326{ 3327 if ((cut_buffer == NULL) 3328 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { 3329 if (cut_buffer != NULL) 3330 free(cut_buffer, M_DEVBUF); 3331 cut_buffer_size = scp->xsize * scp->ysize + 1; 3332 cut_buffer = (u_char *)malloc(cut_buffer_size, 3333 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3334 if (cut_buffer != NULL) 3335 cut_buffer[0] = '\0'; 3336 } 3337} 3338 3339void 3340sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) 3341{ 3342 u_short *usp; 3343 3344 if (lines < scp->ysize) 3345 lines = scp->ysize; 3346 3347 usp = scp->history; 3348 scp->history = NULL; 3349 if (usp != NULL) { 3350 free(usp, M_DEVBUF); 3351 if (extra > 0) 3352 extra_history_size += extra; 3353 } 3354 3355 scp->history_size = lines * scp->xsize; 3356 if (lines > imax(sc_history_size, scp->ysize)) 3357 extra_history_size -= lines - imax(sc_history_size, scp->ysize); 3358 usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 3359 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); 3360 if (usp != NULL) 3361 bzero(usp, scp->history_size * sizeof(u_short)); 3362 scp->history_head = scp->history_pos = usp; 3363 scp->history = usp; 3364} 3365 3366static scr_stat 3367*alloc_scp() 3368{ 3369 scr_stat *scp; 3370 3371 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3372 init_scp(scp); 3373 sc_alloc_scr_buffer(scp, TRUE, TRUE); 3374 if (ISMOUSEAVAIL(scp->adp->va_flags)) 3375 sc_alloc_cut_buffer(scp, TRUE); 3376 sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); 3377/* SOS 3378 if (scp->adp->va_flags & V_ADP_MODECHANGE) 3379 set_mode(scp); 3380*/ 3381 sc_clear_screen(scp); 3382 scp->cursor_saveunder = *scp->cursor_pos; 3383 return scp; 3384} 3385 3386static void 3387init_scp(scr_stat *scp) 3388{ 3389 video_info_t info; 3390 3391 scp->ad = adapter; 3392 scp->adp = vid_get_adapter(scp->ad); 3393 (*vidsw[scp->ad]->get_info)(scp->adp, initial_video_mode, &info); 3394 3395 scp->status = 0; 3396 scp->mode = initial_video_mode; 3397 scp->scr_buf = NULL; 3398 if (info.vi_flags & V_INFO_GRAPHICS) { 3399 scp->status |= GRAPHICS_MODE; 3400 scp->xpixel = info.vi_width; 3401 scp->ypixel = info.vi_height; 3402 scp->xsize = info.vi_width/8; 3403 scp->ysize = info.vi_height/info.vi_cheight; 3404 scp->font_size = FONT_NONE; 3405 } else { 3406 scp->xsize = info.vi_width; 3407 scp->ysize = info.vi_height; 3408 scp->xpixel = scp->xsize*8; 3409 scp->ypixel = scp->ysize*info.vi_cheight; 3410 scp->font_size = info.vi_cheight; 3411 } 3412 scp->xoff = scp->yoff = 0; 3413 scp->xpos = scp->ypos = 0; 3414 scp->saved_xpos = scp->saved_ypos = -1; 3415 scp->start = scp->xsize * scp->ysize; 3416 scp->end = 0; 3417 scp->term.esc = 0; 3418 scp->term.attr_mask = NORMAL_ATTR; 3419 scp->term.cur_attr = 3420 scp->term.cur_color = scp->term.std_color = 3421 current_default->std_color; 3422 scp->term.rev_color = current_default->rev_color; 3423 scp->border = BG_BLACK; 3424 scp->cursor_start = bios_value.cursor_start; 3425 scp->cursor_end = bios_value.cursor_end; 3426 scp->mouse_xpos = scp->xsize*8/2; 3427 scp->mouse_ypos = scp->ysize*scp->font_size/2; 3428 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3429 scp->mouse_signal = 0; 3430 scp->mouse_pid = 0; 3431 scp->mouse_proc = NULL; 3432 scp->kbd_mode = K_XLATE; 3433 scp->bell_pitch = BELL_PITCH; 3434 scp->bell_duration = BELL_DURATION; 3435 scp->status |= (bios_value.shift_state & 0x20) ? NLKED : 0; 3436 scp->status |= CURSOR_ENABLED; 3437 scp->pid = 0; 3438 scp->proc = NULL; 3439 scp->smode.mode = VT_AUTO; 3440 scp->history_head = scp->history_pos = scp->history = NULL; 3441 scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; 3442} 3443 3444static void 3445get_bios_values(void) 3446{ 3447 bios_value.cursor_start = *(u_int8_t *)pa_to_va(0x461); 3448 bios_value.cursor_end = *(u_int8_t *)pa_to_va(0x460); 3449 bios_value.shift_state = *(u_int8_t *)pa_to_va(0x417); 3450} 3451 3452static void 3453history_to_screen(scr_stat *scp) 3454{ 3455 int i; 3456 3457 for (i=0; i<scp->ysize; i++) 3458 bcopy(scp->history + (((scp->history_pos - scp->history) + 3459 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 3460 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 3461 scp->xsize * sizeof(u_short)); 3462 mark_all(scp); 3463} 3464 3465static int 3466history_up_line(scr_stat *scp) 3467{ 3468 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 3469 scp->history_head) { 3470 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 3471 history_to_screen(scp); 3472 return 0; 3473 } 3474 else 3475 return -1; 3476} 3477 3478static int 3479history_down_line(scr_stat *scp) 3480{ 3481 if (scp->history_pos != scp->history_head) { 3482 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 3483 history_to_screen(scp); 3484 return 0; 3485 } 3486 else 3487 return -1; 3488} 3489 3490/* 3491 * scgetc(flags) - get character from keyboard. 3492 * If flags & SCGETC_CN, then avoid harmful side effects. 3493 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3494 * return NOKEY if there is nothing there. 3495 */ 3496static u_int 3497scgetc(keyboard_t *kbd, u_int flags) 3498{ 3499 u_int c; 3500 int this_scr; 3501 int f; 3502 int i; 3503 3504 if (kbd == NULL) 3505 return NOKEY; 3506 3507next_code: 3508 /* I don't like this, but... XXX */ 3509 if (flags & SCGETC_CN) 3510 sccnupdate(cur_console); 3511 /* first see if there is something in the keyboard port */ 3512 for (;;) { 3513 c = kbd_read_char(kbd, !(flags & SCGETC_NONBLOCK)); 3514 if (c == ERRKEY) { 3515 if (!(flags & SCGETC_CN)) 3516 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3517 } else if (c == NOKEY) 3518 return c; 3519 else 3520 break; 3521 } 3522 3523 /* make screensaver happy */ 3524 if (!(c & RELKEY)) 3525 sc_touch_scrn_saver(); 3526 3527#ifdef __i386__ 3528 if (!(flags & SCGETC_CN)) 3529 /* do the /dev/random device a favour */ 3530 add_keyboard_randomness(c); 3531#endif 3532 3533 if (cur_console->kbd_mode != K_XLATE) 3534 return KEYCHAR(c); 3535 3536 /* if scroll-lock pressed allow history browsing */ 3537 if (!ISGRAPHSC(cur_console) && cur_console->history 3538 && cur_console->status & SLKED) { 3539 3540 cur_console->status &= ~CURSOR_ENABLED; 3541 if (!(cur_console->status & BUFFER_SAVED)) { 3542 cur_console->status |= BUFFER_SAVED; 3543 cur_console->history_save = cur_console->history_head; 3544 3545 /* copy screen into top of history buffer */ 3546 for (i=0; i<cur_console->ysize; i++) { 3547 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 3548 cur_console->history_head, 3549 cur_console->xsize * sizeof(u_short)); 3550 cur_console->history_head += cur_console->xsize; 3551 if (cur_console->history_head + cur_console->xsize > 3552 cur_console->history + cur_console->history_size) 3553 cur_console->history_head=cur_console->history; 3554 } 3555 cur_console->history_pos = cur_console->history_head; 3556 history_to_screen(cur_console); 3557 } 3558 switch (c) { 3559 /* FIXME: key codes */ 3560 case SPCLKEY | FKEY | F(49): /* home key */ 3561 remove_cutmarking(cur_console); 3562 cur_console->history_pos = cur_console->history_head; 3563 history_to_screen(cur_console); 3564 goto next_code; 3565 3566 case SPCLKEY | FKEY | F(57): /* end key */ 3567 remove_cutmarking(cur_console); 3568 cur_console->history_pos = 3569 WRAPHIST(cur_console, cur_console->history_head, 3570 cur_console->xsize*cur_console->ysize); 3571 history_to_screen(cur_console); 3572 goto next_code; 3573 3574 case SPCLKEY | FKEY | F(50): /* up arrow key */ 3575 remove_cutmarking(cur_console); 3576 if (history_up_line(cur_console)) 3577 if (!(flags & SCGETC_CN)) 3578 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3579 goto next_code; 3580 3581 case SPCLKEY | FKEY | F(58): /* down arrow key */ 3582 remove_cutmarking(cur_console); 3583 if (history_down_line(cur_console)) 3584 if (!(flags & SCGETC_CN)) 3585 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3586 goto next_code; 3587 3588 case SPCLKEY | FKEY | F(51): /* page up key */ 3589 remove_cutmarking(cur_console); 3590 for (i=0; i<cur_console->ysize; i++) 3591 if (history_up_line(cur_console)) { 3592 if (!(flags & SCGETC_CN)) 3593 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3594 break; 3595 } 3596 goto next_code; 3597 3598 case SPCLKEY | FKEY | F(59): /* page down key */ 3599 remove_cutmarking(cur_console); 3600 for (i=0; i<cur_console->ysize; i++) 3601 if (history_down_line(cur_console)) { 3602 if (!(flags & SCGETC_CN)) 3603 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3604 break; 3605 } 3606 goto next_code; 3607 } 3608 } 3609 3610 /* 3611 * Process and consume special keys here. Return a plain char code 3612 * or a char code with the META flag or a function key code. 3613 */ 3614 if (c & RELKEY) { 3615 /* key released */ 3616 /* goto next_code */ 3617 } else { 3618 /* key pressed */ 3619 if (c & SPCLKEY) { 3620 c &= ~SPCLKEY; 3621 switch (KEYCHAR(c)) { 3622 /* LOCKING KEYS */ 3623 case NLK: case CLK: case ALK: 3624 break; 3625 case SLK: 3626 kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&f); 3627 if (f & SLKED) { 3628 cur_console->status |= SLKED; 3629 } else { 3630 if (cur_console->status & SLKED) { 3631 cur_console->status &= ~SLKED; 3632 if (cur_console->status & BUFFER_SAVED) { 3633 int i; 3634 u_short *ptr = cur_console->history_save; 3635 3636 for (i=0; i<cur_console->ysize; i++) { 3637 bcopy(ptr, 3638 cur_console->scr_buf + 3639 (cur_console->xsize*i), 3640 cur_console->xsize * sizeof(u_short)); 3641 ptr += cur_console->xsize; 3642 if (ptr + cur_console->xsize > 3643 cur_console->history + 3644 cur_console->history_size) 3645 ptr = cur_console->history; 3646 } 3647 cur_console->status &= ~BUFFER_SAVED; 3648 cur_console->history_head=cur_console->history_save; 3649 cur_console->status |= CURSOR_ENABLED; 3650 mark_all(cur_console); 3651 } 3652 scstart(VIRTUAL_TTY(get_scr_num())); 3653 } 3654 } 3655 break; 3656 3657 /* NON-LOCKING KEYS */ 3658 case NOP: 3659 case LSH: case RSH: case LCTR: case RCTR: 3660 case LALT: case RALT: case ASH: case META: 3661 break; 3662 3663 case BTAB: 3664 return c; 3665 3666 case SPSC: 3667 /* force activatation/deactivation of the screen saver */ 3668 if (!scrn_blanked) { 3669 run_scrn_saver = TRUE; 3670 scrn_time_stamp -= scrn_blank_time; 3671 } 3672#if NSPLASH > 0 3673 if (cold) { 3674 /* 3675 * While devices are being probed, the screen saver need 3676 * to be invoked explictly. XXX 3677 */ 3678 if (scrn_blanked) { 3679 scsplash_stick(FALSE); 3680 stop_scrn_saver(current_saver); 3681 } else { 3682 if (!ISGRAPHSC(cur_console)) { 3683 scsplash_stick(TRUE); 3684 (*current_saver)(TRUE); 3685 } 3686 } 3687 } 3688#endif /* NSPLASH */ 3689 break; 3690 3691 case RBT: 3692#ifndef SC_DISABLE_REBOOT 3693 shutdown_nice(); 3694#endif 3695 break; 3696 3697#if NAPM > 0 3698 case SUSP: 3699 apm_suspend(PMST_SUSPEND); 3700 break; 3701 case STBY: 3702 apm_suspend(PMST_STANDBY); 3703 break; 3704#else 3705 case SUSP: 3706 case STBY: 3707 break; 3708#endif 3709 3710 case DBG: 3711#ifdef DDB /* try to switch to console 0 */ 3712 /* 3713 * TRY to make sure the screen saver is stopped, 3714 * and the screen is updated before switching to 3715 * the vty0. 3716 */ 3717 scrn_timer((void *)FALSE); 3718 if (cur_console->smode.mode == VT_AUTO && 3719 console[0]->smode.mode == VT_AUTO) 3720 switch_scr(cur_console, 0); 3721 Debugger("manual escape to debugger"); 3722#else 3723 printf("No debugger in kernel\n"); 3724#endif 3725 break; 3726 3727 case NEXT: 3728 this_scr = get_scr_num(); 3729 for (i = this_scr + 1; i != this_scr; i = (i + 1)%MAXCONS) { 3730 struct tty *tp = VIRTUAL_TTY(i); 3731 if (tp->t_state & TS_ISOPEN) { 3732 switch_scr(cur_console, i); 3733 break; 3734 } 3735 } 3736 break; 3737 3738 default: 3739 if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) { 3740 switch_scr(cur_console, KEYCHAR(c) - F_SCR); 3741 break; 3742 } 3743 /* assert(c & FKEY) */ 3744 return c; 3745 } 3746 /* goto next_code */ 3747 } else { 3748 /* regular keys (maybe MKEY is set) */ 3749 return c; 3750 } 3751 } 3752 3753 goto next_code; 3754} 3755 3756int 3757scmmap(dev_t dev, vm_offset_t offset, int nprot) 3758{ 3759 struct tty *tp; 3760 struct scr_stat *scp; 3761 3762 tp = scdevtotty(dev); 3763 if (!tp) 3764 return ENXIO; 3765 scp = sc_get_scr_stat(tp->t_dev); 3766 return (*vidsw[scp->ad]->mmap)(scp->adp, offset); 3767} 3768 3769/* 3770 * Calculate hardware attributes word using logical attributes mask and 3771 * hardware colors 3772 */ 3773 3774static int 3775mask2attr(struct term_stat *term) 3776{ 3777 int attr, mask = term->attr_mask; 3778 3779 if (mask & REVERSE_ATTR) { 3780 attr = ((mask & FOREGROUND_CHANGED) ? 3781 ((term->cur_color & 0xF000) >> 4) : 3782 (term->rev_color & 0x0F00)) | 3783 ((mask & BACKGROUND_CHANGED) ? 3784 ((term->cur_color & 0x0F00) << 4) : 3785 (term->rev_color & 0xF000)); 3786 } else 3787 attr = term->cur_color; 3788 3789 /* XXX: underline mapping for Hercules adapter can be better */ 3790 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3791 attr ^= 0x0800; 3792 if (mask & BLINK_ATTR) 3793 attr ^= 0x8000; 3794 3795 return attr; 3796} 3797 3798static int 3799save_kbd_state(scr_stat *scp) 3800{ 3801 int state; 3802 int error; 3803 3804 error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state); 3805 if (error == ENOIOCTL) 3806 error = ENODEV; 3807 if (error == 0) { 3808 scp->status &= ~LOCK_MASK; 3809 scp->status |= state; 3810 } 3811 return error; 3812} 3813 3814static int 3815update_kbd_state(int new_bits, int mask) 3816{ 3817 int state; 3818 int error; 3819 3820 if (mask != LOCK_MASK) { 3821 error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state); 3822 if (error == ENOIOCTL) 3823 error = ENODEV; 3824 if (error) 3825 return error; 3826 state &= ~mask; 3827 state |= new_bits & mask; 3828 } else { 3829 state = new_bits & LOCK_MASK; 3830 } 3831 error = kbd_ioctl(kbd, KDSKBSTATE, (caddr_t)&state); 3832 if (error == ENOIOCTL) 3833 error = ENODEV; 3834 return error; 3835} 3836 3837static int 3838update_kbd_leds(int which) 3839{ 3840 int error; 3841 3842 which &= LOCK_MASK; 3843 error = kbd_ioctl(kbd, KDSETLED, (caddr_t)&which); 3844 if (error == ENOIOCTL) 3845 error = ENODEV; 3846 return error; 3847} 3848 3849int 3850set_mode(scr_stat *scp) 3851{ 3852 video_info_t info; 3853 3854 /* reject unsupported mode */ 3855 if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info)) 3856 return 1; 3857 3858 /* if this vty is not currently showing, do nothing */ 3859 if (scp != cur_console) 3860 return 0; 3861 3862 /* setup video hardware for the given mode */ 3863 (*vidsw[scp->ad]->set_mode)(scp->adp, scp->mode); 3864 3865 if (!(scp->status & GRAPHICS_MODE)) { 3866 /* load appropriate font */ 3867 if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->adp->va_flags)) { 3868 if (scp->font_size < 14) { 3869 if (fonts_loaded & FONT_8) 3870 copy_font(scp, LOAD, 8, font_8); 3871 } else if (scp->font_size >= 16) { 3872 if (fonts_loaded & FONT_16) 3873 copy_font(scp, LOAD, 16, font_16); 3874 } else { 3875 if (fonts_loaded & FONT_14) 3876 copy_font(scp, LOAD, 14, font_14); 3877 } 3878 /* 3879 * FONT KLUDGE: 3880 * This is an interim kludge to display correct font. 3881 * Always use the font page #0 on the video plane 2. 3882 * Somehow we cannot show the font in other font pages on 3883 * some video cards... XXX 3884 */ 3885 (*vidsw[scp->ad]->show_font)(scp->adp, 0); 3886 } 3887 mark_all(scp); 3888 } 3889 3890 if (scp->status & PIXEL_MODE) 3891 bzero_io(scp->adp->va_window, scp->xpixel*scp->ypixel/8); 3892 3893 set_border(scp, scp->border); 3894 3895 /* move hardware cursor out of the way */ 3896 (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1); 3897 3898 return 0; 3899} 3900 3901void 3902set_border(scr_stat *scp, int color) 3903{ 3904 vm_offset_t p; 3905 int xoff; 3906 int yoff; 3907 int xlen; 3908 int ylen; 3909 int i; 3910 3911 (*vidsw[scp->ad]->set_border)(scp->adp, color); 3912 3913 if (scp->status & PIXEL_MODE) { 3914 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 3915 outw(GDCIDX, 0x0003); /* data rotate/function select */ 3916 outw(GDCIDX, 0x0f01); /* set/reset enable */ 3917 outw(GDCIDX, 0xff08); /* bit mask */ 3918 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 3919 p = scp->adp->va_window; 3920 xoff = scp->xoff; 3921 yoff = scp->yoff*scp->font_size; 3922 xlen = scp->xpixel/8; 3923 ylen = scp->ysize*scp->font_size; 3924 if (yoff > 0) { 3925 bzero_io(p, xlen*yoff); 3926 bzero_io(p + xlen*(yoff + ylen), 3927 xlen*scp->ypixel - xlen*(yoff + ylen)); 3928 } 3929 if (xoff > 0) { 3930 for (i = 0; i < ylen; ++i) { 3931 bzero_io(p + xlen*(yoff + i), xoff); 3932 bzero_io(p + xlen*(yoff + i) + xoff + scp->xsize, 3933 xlen - xoff - scp->xsize); 3934 } 3935 } 3936 outw(GDCIDX, 0x0000); /* set/reset */ 3937 outw(GDCIDX, 0x0001); /* set/reset enable */ 3938 } 3939} 3940 3941void 3942copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) 3943{ 3944 /* 3945 * FONT KLUDGE: 3946 * This is an interim kludge to display correct font. 3947 * Always use the font page #0 on the video plane 2. 3948 * Somehow we cannot show the font in other font pages on 3949 * some video cards... XXX 3950 */ 3951 font_loading_in_progress = TRUE; 3952 if (operation == LOAD) { 3953 (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, buf, 0, 256); 3954 if (sc_flags & CHAR_CURSOR) 3955 set_destructive_cursor(scp); 3956 } else if (operation == SAVE) { 3957 (*vidsw[scp->ad]->save_font)(scp->adp, 0, font_size, buf, 0, 256); 3958 } 3959 font_loading_in_progress = FALSE; 3960} 3961 3962static void 3963set_destructive_cursor(scr_stat *scp) 3964{ 3965 u_char cursor[32]; 3966 u_char *font_buffer; 3967 int font_size; 3968 int crtc_addr; 3969 int i; 3970 3971 if (!ISFONTAVAIL(scp->adp->va_flags) 3972 || (scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 3973 return; 3974 3975 if (scp->font_size < 14) { 3976 font_buffer = font_8; 3977 font_size = 8; 3978 } else if (scp->font_size >= 16) { 3979 font_buffer = font_16; 3980 font_size = 16; 3981 } else { 3982 font_buffer = font_14; 3983 font_size = 14; 3984 } 3985 3986 if (scp->status & MOUSE_VISIBLE) { 3987 if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) 3988 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 3989 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1) 3990 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 3991 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2) 3992 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 3993 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3) 3994 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 3995 else 3996 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 3997 cursor, scp->font_size); 3998 } 3999 else 4000 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 4001 cursor, scp->font_size); 4002 for (i=0; i<32; i++) 4003 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 4004 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 4005 cursor[i] |= 0xff; 4006#if 1 4007 crtc_addr = scp->adp->va_crtc_addr; 4008 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 4009#endif 4010 font_loading_in_progress = TRUE; 4011 (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); 4012 font_loading_in_progress = FALSE; 4013} 4014 4015void 4016sc_move_mouse(scr_stat *scp, int x, int y) 4017{ 4018 scp->mouse_xpos = x; 4019 scp->mouse_ypos = y; 4020 scp->mouse_pos = scp->mouse_oldpos = 4021 scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8; 4022} 4023 4024static void 4025set_mouse_pos(scr_stat *scp) 4026{ 4027 static int last_xpos = -1, last_ypos = -1; 4028 4029 if (scp->mouse_xpos < 0) 4030 scp->mouse_xpos = 0; 4031 if (scp->mouse_ypos < 0) 4032 scp->mouse_ypos = 0; 4033 if (!ISTEXTSC(scp)) { 4034 if (scp->mouse_xpos > scp->xpixel-1) 4035 scp->mouse_xpos = scp->xpixel-1; 4036 if (scp->mouse_ypos > scp->ypixel-1) 4037 scp->mouse_ypos = scp->ypixel-1; 4038 return; 4039 } 4040 if (scp->mouse_xpos > (scp->xsize*8)-1) 4041 scp->mouse_xpos = (scp->xsize*8)-1; 4042 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) 4043 scp->mouse_ypos = (scp->ysize*scp->font_size)-1; 4044 4045 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 4046 scp->status |= MOUSE_MOVED; 4047 4048 scp->mouse_pos = scp->scr_buf + 4049 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 4050 4051 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 4052 mouse_cut(scp); 4053 } 4054} 4055 4056#define isspace(c) (((c) & 0xff) == ' ') 4057 4058static int 4059skip_spc_right(scr_stat *scp, u_short *p) 4060{ 4061 int i; 4062 4063 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4064 if (!isspace(*p)) 4065 break; 4066 ++p; 4067 } 4068 return i; 4069} 4070 4071static int 4072skip_spc_left(scr_stat *scp, u_short *p) 4073{ 4074 int i; 4075 4076 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { 4077 if (!isspace(*p)) 4078 break; 4079 --p; 4080 } 4081 return i; 4082} 4083 4084static void 4085mouse_cut(scr_stat *scp) 4086{ 4087 u_short *end; 4088 u_short *p; 4089 int i = 0; 4090 int j = 0; 4091 4092 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? 4093 scp->mouse_pos + 1 : scp->mouse_pos; 4094 end = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4095 scp->mouse_cut_start : scp->mouse_cut_end; 4096 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4097 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { 4098 cut_buffer[i] = *p & 0xff; 4099 /* remember the position of the last non-space char */ 4100 if (!isspace(cut_buffer[i++])) 4101 j = i; 4102 /* trim trailing blank when crossing lines */ 4103 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 4104 cut_buffer[j++] = '\r'; 4105 i = j; 4106 } 4107 } 4108 cut_buffer[i] = '\0'; 4109 4110 /* scan towards the end of the last line */ 4111 --p; 4112 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4113 if (!isspace(*p)) 4114 break; 4115 ++p; 4116 } 4117 /* if there is nothing but blank chars, trim them, but mark towards eol */ 4118 if (i >= scp->xsize) { 4119 if (scp->mouse_cut_start > scp->mouse_cut_end) 4120 scp->mouse_cut_start = p; 4121 else 4122 scp->mouse_cut_end = p; 4123 cut_buffer[j++] = '\r'; 4124 cut_buffer[j] = '\0'; 4125 } 4126 4127 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 4128 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 4129} 4130 4131static void 4132mouse_cut_start(scr_stat *scp) 4133{ 4134 int i; 4135 4136 if (scp->status & MOUSE_VISIBLE) { 4137 if (scp->mouse_pos == scp->mouse_cut_start && 4138 scp->mouse_cut_start == scp->mouse_cut_end - 1) { 4139 cut_buffer[0] = '\0'; 4140 remove_cutmarking(scp); 4141 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 4142 /* if the pointer is on trailing blank chars, mark towards eol */ 4143 i = skip_spc_left(scp, scp->mouse_pos) + 1; 4144 scp->mouse_cut_start = scp->scr_buf + 4145 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; 4146 scp->mouse_cut_end = scp->scr_buf + 4147 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; 4148 cut_buffer[0] = '\r'; 4149 cut_buffer[1] = '\0'; 4150 scp->status |= MOUSE_CUTTING; 4151 } else { 4152 scp->mouse_cut_start = scp->mouse_pos; 4153 scp->mouse_cut_end = scp->mouse_cut_start + 1; 4154 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 4155 cut_buffer[1] = '\0'; 4156 scp->status |= MOUSE_CUTTING; 4157 } 4158 mark_all(scp); 4159 /* delete all other screens cut markings */ 4160 for (i=0; i<MAXCONS; i++) { 4161 if (console[i] == NULL || console[i] == scp) 4162 continue; 4163 remove_cutmarking(console[i]); 4164 } 4165 } 4166} 4167 4168static void 4169mouse_cut_end(scr_stat *scp) 4170{ 4171 if (scp->status & MOUSE_VISIBLE) { 4172 scp->status &= ~MOUSE_CUTTING; 4173 } 4174} 4175 4176static void 4177mouse_cut_word(scr_stat *scp) 4178{ 4179 u_short *p; 4180 u_short *sol; 4181 u_short *eol; 4182 int i; 4183 4184 /* 4185 * Because we don't have locale information in the kernel, 4186 * we only distinguish space char and non-space chars. Punctuation 4187 * chars, symbols and other regular chars are all treated alike. 4188 */ 4189 if (scp->status & MOUSE_VISIBLE) { 4190 sol = scp->scr_buf 4191 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4192 eol = sol + scp->xsize; 4193 if (isspace(*scp->mouse_pos)) { 4194 for (p = scp->mouse_pos; p >= sol; --p) 4195 if (!isspace(*p)) 4196 break; 4197 scp->mouse_cut_start = ++p; 4198 for (p = scp->mouse_pos; p < eol; ++p) 4199 if (!isspace(*p)) 4200 break; 4201 scp->mouse_cut_end = p; 4202 } else { 4203 for (p = scp->mouse_pos; p >= sol; --p) 4204 if (isspace(*p)) 4205 break; 4206 scp->mouse_cut_start = ++p; 4207 for (p = scp->mouse_pos; p < eol; ++p) 4208 if (isspace(*p)) 4209 break; 4210 scp->mouse_cut_end = p; 4211 } 4212 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4213 cut_buffer[i++] = *p & 0xff; 4214 cut_buffer[i] = '\0'; 4215 scp->status |= MOUSE_CUTTING; 4216 } 4217} 4218 4219static void 4220mouse_cut_line(scr_stat *scp) 4221{ 4222 u_short *p; 4223 int i; 4224 4225 if (scp->status & MOUSE_VISIBLE) { 4226 scp->mouse_cut_start = scp->scr_buf 4227 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4228 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; 4229 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4230 cut_buffer[i++] = *p & 0xff; 4231 cut_buffer[i++] = '\r'; 4232 cut_buffer[i] = '\0'; 4233 scp->status |= MOUSE_CUTTING; 4234 } 4235} 4236 4237static void 4238mouse_cut_extend(scr_stat *scp) 4239{ 4240 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 4241 && (scp->mouse_cut_start != NULL)) { 4242 mouse_cut(scp); 4243 scp->status |= MOUSE_CUTTING; 4244 } 4245} 4246 4247static void 4248mouse_paste(scr_stat *scp) 4249{ 4250 if (scp->status & MOUSE_VISIBLE) { 4251 struct tty *tp; 4252 u_char *ptr = cut_buffer; 4253 4254 tp = VIRTUAL_TTY(get_scr_num()); 4255 while (*ptr) 4256 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 4257 } 4258} 4259 4260static void 4261draw_mouse_image(scr_stat *scp) 4262{ 4263 u_short buffer[32]; 4264 u_short xoffset, yoffset; 4265 vm_offset_t crt_pos = scp->adp->va_window + 2*(scp->mouse_pos - scp->scr_buf); 4266 u_char *font_buffer; 4267 int font_size; 4268 int crtc_addr; 4269 int i; 4270 4271 if (scp->font_size < 14) { 4272 font_buffer = font_8; 4273 font_size = 8; 4274 } else if (scp->font_size >= 16) { 4275 font_buffer = font_16; 4276 font_size = 16; 4277 } else { 4278 font_buffer = font_14; 4279 font_size = 14; 4280 } 4281 4282 xoffset = scp->mouse_xpos % 8; 4283 yoffset = scp->mouse_ypos % scp->font_size; 4284 4285 /* prepare mousepointer char's bitmaps */ 4286 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 4287 &scp->mouse_cursor[0], font_size); 4288 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 4289 &scp->mouse_cursor[32], font_size); 4290 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 4291 &scp->mouse_cursor[64], font_size); 4292 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 4293 &scp->mouse_cursor[96], font_size); 4294 for (i=0; i<font_size; i++) { 4295 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 4296 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 4297 } 4298 4299 /* now and-or in the mousepointer image */ 4300 for (i=0; i<16; i++) { 4301 buffer[i+yoffset] = 4302 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 4303 | (mouse_or_mask[i] >> xoffset); 4304 } 4305 for (i=0; i<font_size; i++) { 4306 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 4307 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 4308 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 4309 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 4310 } 4311 4312 scp->mouse_oldpos = scp->mouse_pos; 4313 4314#if 1 4315 /* wait for vertical retrace to avoid jitter on some videocards */ 4316 crtc_addr = scp->adp->va_crtc_addr; 4317 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 4318#endif 4319 font_loading_in_progress = TRUE; 4320 (*vidsw[scp->ad]->load_font)(scp->adp, 0, 32, scp->mouse_cursor, 4321 SC_MOUSE_CHAR, 4); 4322 font_loading_in_progress = FALSE; 4323 4324 writew(crt_pos, (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR); 4325 writew(crt_pos+2*scp->xsize, 4326 (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2)); 4327 if (scp->mouse_xpos < (scp->xsize-1)*8) { 4328 writew(crt_pos + 2, (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1)); 4329 writew(crt_pos+2*scp->xsize + 2, 4330 (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3)); 4331 } 4332 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 4333 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 4334} 4335 4336static void 4337remove_mouse_image(scr_stat *scp) 4338{ 4339 vm_offset_t crt_pos; 4340 4341 if (!ISTEXTSC(scp)) 4342 return; 4343 4344 crt_pos = scp->adp->va_window + 2*(scp->mouse_oldpos - scp->scr_buf); 4345 writew(crt_pos, *(scp->mouse_oldpos)); 4346 writew(crt_pos+2, *(scp->mouse_oldpos+1)); 4347 writew(crt_pos+2*scp->xsize, *(scp->mouse_oldpos+scp->xsize)); 4348 writew(crt_pos+2*scp->xsize+2, *(scp->mouse_oldpos+scp->xsize+1)); 4349 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 4350 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 4351} 4352 4353static void 4354draw_cutmarking(scr_stat *scp) 4355{ 4356 vm_offset_t crt_pos; 4357 u_short *ptr; 4358 u_short och, nch; 4359 4360 crt_pos = scp->adp->va_window; 4361 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 4362 nch = och = readw(crt_pos + 2*(ptr - scp->scr_buf)); 4363 /* are we outside the selected area ? */ 4364 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 4365 scp->mouse_cut_end : scp->mouse_cut_start) || 4366 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? 4367 scp->mouse_cut_start : scp->mouse_cut_end)) { 4368 if (ptr != scp->cursor_pos) 4369 nch = (och & 0xff) | (*ptr & 0xff00); 4370 } 4371 else { 4372 /* are we clear of the cursor image ? */ 4373 if (ptr != scp->cursor_pos) 4374 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 4375 else { 4376 if (sc_flags & CHAR_CURSOR) 4377 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 4378 else 4379 if (!(sc_flags & BLINK_CURSOR)) 4380 nch = (och & 0xff) | (*ptr & 0xff00); 4381 } 4382 } 4383 if (nch != och) 4384 writew(crt_pos + 2*(ptr - scp->scr_buf), nch); 4385 } 4386} 4387 4388static void 4389remove_cutmarking(scr_stat *scp) 4390{ 4391 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 4392 scp->status &= ~MOUSE_CUTTING; 4393 mark_all(scp); 4394} 4395 4396static void 4397do_bell(scr_stat *scp, int pitch, int duration) 4398{ 4399 if (cold || shutdown_in_progress) 4400 return; 4401 4402 if (scp != cur_console && (sc_flags & QUIET_BELL)) 4403 return; 4404 4405 if (sc_flags & VISUAL_BELL) { 4406 if (blink_in_progress) 4407 return; 4408 blink_in_progress = 4; 4409 if (scp != cur_console) 4410 blink_in_progress += 2; 4411 blink_screen(cur_console); 4412 } else { 4413 if (scp != cur_console) 4414 pitch *= 2; 4415 sysbeep(pitch, duration); 4416 } 4417} 4418 4419static void 4420blink_screen(void *arg) 4421{ 4422 scr_stat *scp = arg; 4423 4424 if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { 4425 blink_in_progress = FALSE; 4426 mark_all(scp); 4427 if (delayed_next_scr) 4428 switch_scr(scp, delayed_next_scr - 1); 4429 } 4430 else { 4431 if (blink_in_progress & 1) 4432 fillw_io(kernel_default.std_color | scr_map[0x20], 4433 scp->adp->va_window, 4434 scp->xsize * scp->ysize); 4435 else 4436 fillw_io(kernel_default.rev_color | scr_map[0x20], 4437 scp->adp->va_window, 4438 scp->xsize * scp->ysize); 4439 blink_in_progress--; 4440 timeout(blink_screen, scp, hz / 10); 4441 } 4442} 4443 4444void 4445sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) 4446{ 4447 u_char *font; 4448 vm_offset_t d; 4449 vm_offset_t e; 4450 u_char *f; 4451 int font_size; 4452 int line_length; 4453 int xsize; 4454 u_short bg; 4455 int i, j; 4456 u_char c; 4457 4458 if (ISTEXTSC(scp)) { 4459 bcopy_toio(p + from, scp->adp->va_window + 2*from, 4460 (to - from + 1)*sizeof(u_short)); 4461 } else /* if ISPIXELSC(scp) */ { 4462 if (mark) 4463 mark = 255; 4464 font_size = scp->font_size; 4465 if (font_size < 14) 4466 font = font_8; 4467 else if (font_size >= 16) 4468 font = font_16; 4469 else 4470 font = font_14; 4471 line_length = scp->xpixel/8; 4472 xsize = scp->xsize; 4473 d = scp->adp->va_window 4474 + scp->xoff + scp->yoff*font_size*line_length 4475 + (from%xsize) + font_size*line_length*(from/xsize); 4476 4477 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4478 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4479 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4480 bg = -1; 4481 for (i = from ; i <= to ; i++) { 4482 /* set background color in EGA/VGA latch */ 4483 if (bg != (p[i] & 0xf000)) { 4484 bg = (p[i] & 0xf000); 4485 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4486 outw(GDCIDX, 0xff08); /* bit mask */ 4487 writeb(d, 0); 4488 c = readb(d); /* set the background color in the latch */ 4489 } 4490 /* foreground color */ 4491 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4492 e = d; 4493 f = &font[(p[i] & 0x00ff)*font_size]; 4494 for (j = 0 ; j < font_size; j++, f++) { 4495 outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */ 4496 writeb(e, 0); 4497 e += line_length; 4498 } 4499 d++; 4500 if ((i % xsize) == xsize - 1) 4501 d += scp->xoff*2 + (font_size - 1)*line_length; 4502 } 4503 outw(GDCIDX, 0x0000); /* set/reset */ 4504 outw(GDCIDX, 0x0001); /* set/reset enable */ 4505 outw(GDCIDX, 0xff08); /* bit mask */ 4506 4507#if 0 /* VGA only */ 4508 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4509 outw(GDCIDX, 0x0003); /* data rotate/function select */ 4510 outw(GDCIDX, 0x0f01); /* set/reset enable */ 4511 outw(GDCIDX, 0xff08); /* bit mask */ 4512 bg = -1; 4513 for (i = from ; i <= to ; i++) { 4514 /* set background color in EGA/VGA latch */ 4515 if (bg != (p[i] & 0xf000)) { 4516 bg = (p[i] & 0xf000); 4517 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4518 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ 4519 *d = 0; 4520 c = *d; /* set the background color in the latch */ 4521 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 4522 } 4523 /* foreground color */ 4524 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ 4525 e = (u_char *)d; 4526 f = &font[(p[i] & 0x00ff)*font_size]; 4527 for (j = 0 ; j < font_size; j++, f++) { 4528 *e = *f^mark; 4529 e += line_length; 4530 } 4531 d++; 4532 if ((i % xsize) == xsize - 1) 4533 d += scp->xoff*2 + (font_size - 1)*line_length; 4534 } 4535 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 4536 outw(GDCIDX, 0x0000); /* set/reset */ 4537 outw(GDCIDX, 0x0001); /* set/reset enable */ 4538#endif /* 0 */ 4539 } 4540} 4541 4542#endif /* NSC */ 4543