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