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