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