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