syscons.c revision 26807
1/*- 2 * Copyright (c) 1992-1997 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 * in this position and unchanged. 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 withough 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.216 1997/05/15 05:43:57 yokota Exp $ 29 */ 30 31#include "sc.h" 32#include "apm.h" 33#include "opt_ddb.h" 34#include "opt_syscons.h" 35 36#if NSC > 0 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/conf.h> 40#include <sys/proc.h> 41#include <sys/signalvar.h> 42#include <sys/tty.h> 43#include <sys/uio.h> 44#include <sys/callout.h> 45#include <sys/kernel.h> 46#include <sys/syslog.h> 47#include <sys/errno.h> 48#include <sys/malloc.h> 49#ifdef DEVFS 50#include <sys/devfsext.h> 51#endif 52 53#include <machine/clock.h> 54#include <machine/cons.h> 55#include <machine/console.h> 56#include <machine/md_var.h> 57#include <machine/psl.h> 58#include <machine/frame.h> 59#include <machine/pc/display.h> 60#include <machine/apm_bios.h> 61#include <machine/random.h> 62 63#include <vm/vm.h> 64#include <vm/vm_param.h> 65#include <vm/pmap.h> 66 67#include <i386/isa/isa.h> 68#include <i386/isa/isa_device.h> 69#include <i386/isa/timerreg.h> 70#include <i386/isa/kbdtables.h> 71#include <i386/isa/kbdio.h> 72#include <i386/isa/syscons.h> 73 74#if !defined(MAXCONS) 75#define MAXCONS 16 76#endif 77 78#define COLD 0 79#define WARM 1 80 81/* XXX use sc_bcopy where video memory is concerned */ 82#define sc_bcopy generic_bcopy 83extern void generic_bcopy(const void *, void *, size_t); 84 85static default_attr user_default = { 86 (FG_LIGHTGREY | BG_BLACK) << 8, 87 (FG_BLACK | BG_LIGHTGREY) << 8 88}; 89 90static default_attr kernel_default = { 91 (FG_WHITE | BG_BLACK) << 8, 92 (FG_BLACK | BG_LIGHTGREY) << 8 93}; 94 95static scr_stat main_console; 96static scr_stat *console[MAXCONS]; 97#ifdef DEVFS 98static void *sc_devfs_token[MAXCONS]; 99#endif 100 scr_stat *cur_console; 101static scr_stat *new_scp, *old_scp; 102static term_stat kernel_console; 103static default_attr *current_default; 104static int flags = 0; 105static int sc_port = IO_KBD; 106static KBDC sc_kbdc = NULL; 107static char init_done = COLD; 108static u_short sc_buffer[ROW*COL]; 109static char switch_in_progress = FALSE; 110static char write_in_progress = FALSE; 111static char blink_in_progress = FALSE; 112static int blinkrate = 0; 113 u_int crtc_addr = MONO_BASE; 114 char crtc_type = KD_MONO; 115 char crtc_vga = FALSE; 116static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 117static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 118static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 119static int delayed_next_scr = FALSE; 120static long scrn_blank_time = 0; /* screen saver timeout value */ 121 int scrn_blanked = FALSE; /* screen saver active flag */ 122static long scrn_time_stamp; 123 u_char scr_map[256]; 124 u_char scr_rmap[256]; 125 char *video_mode_ptr = NULL; 126 int fonts_loaded = 0; 127 char font_8[256*8]; 128 char font_14[256*14]; 129 char font_16[256*16]; 130 char palette[256*3]; 131static char vgaregs[64]; 132static char *cut_buffer; 133static u_short mouse_and_mask[16] = { 134 0xc000, 0xe000, 0xf000, 0xf800, 135 0xfc00, 0xfe00, 0xff00, 0xff80, 136 0xfe00, 0x1e00, 0x1f00, 0x0f00, 137 0x0f00, 0x0000, 0x0000, 0x0000 138 }; 139static u_short mouse_or_mask[16] = { 140 0x0000, 0x4000, 0x6000, 0x7000, 141 0x7800, 0x7c00, 0x7e00, 0x6800, 142 0x0c00, 0x0c00, 0x0600, 0x0600, 143 0x0000, 0x0000, 0x0000, 0x0000 144 }; 145 146static void none_saver(int blank) { } 147void (*current_saver)(int blank) = none_saver; 148int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, 149 int flag, struct proc *p) = NULL; 150 151/* OS specific stuff */ 152#ifdef not_yet_done 153#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 154struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 155struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) 156struct tty *sccons[MAXCONS+2]; 157#else 158#define VIRTUAL_TTY(x) &sccons[x] 159#define CONSOLE_TTY &sccons[MAXCONS] 160#define MOUSE_TTY &sccons[MAXCONS+1] 161static struct tty sccons[MAXCONS+2]; 162#endif 163#define SC_MOUSE 128 164#define SC_CONSOLE 255 165#define MONO_BUF pa_to_va(0xB0000) 166#define CGA_BUF pa_to_va(0xB8000) 167u_short *Crtat; 168static const int nsccons = MAXCONS+2; 169 170#define WRAPHIST(scp, pointer, offset)\ 171 ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\ 172 + (offset)) % (scp->history_size))) 173#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 174 175/* this should really be in `rtc.h' */ 176#define RTC_EQUIPMENT 0x14 177 178/* prototypes */ 179static int scattach(struct isa_device *dev); 180static int scparam(struct tty *tp, struct termios *t); 181static int scprobe(struct isa_device *dev); 182static int scvidprobe(int unit, int flags); 183static int sckbdprobe(int unit, int flags); 184static void scstart(struct tty *tp); 185static void scmousestart(struct tty *tp); 186static void scinit(void); 187static u_int scgetc(u_int flags); 188#define SCGETC_CN 1 189#define SCGETC_NONBLOCK 2 190static scr_stat *get_scr_stat(dev_t dev); 191static scr_stat *alloc_scp(void); 192static void init_scp(scr_stat *scp); 193static int get_scr_num(void); 194static timeout_t scrn_timer; 195static void clear_screen(scr_stat *scp); 196static int switch_scr(scr_stat *scp, u_int next_scr); 197static void exchange_scr(void); 198static inline void move_crsr(scr_stat *scp, int x, int y); 199static void scan_esc(scr_stat *scp, u_char c); 200static void draw_cursor_image(scr_stat *scp); 201static void remove_cursor_image(scr_stat *scp); 202static void ansi_put(scr_stat *scp, u_char *buf, int len); 203static u_char *get_fstr(u_int c, u_int *len); 204static void history_to_screen(scr_stat *scp); 205static int history_up_line(scr_stat *scp); 206static int history_down_line(scr_stat *scp); 207static int mask2attr(struct term_stat *term); 208static void set_keyboard(int command, int data); 209static void update_leds(int which); 210static void set_vgaregs(char *modetable); 211static void read_vgaregs(char *buf); 212static int comp_vgaregs(u_char *buf1, u_char *buf2); 213static void dump_vgaregs(u_char *buf); 214static void set_font_mode(void); 215static void set_normal_mode(void); 216static void set_destructive_cursor(scr_stat *scp); 217static void set_mouse_pos(scr_stat *scp); 218static void mouse_cut_start(scr_stat *scp); 219static void mouse_cut_end(scr_stat *scp); 220static void mouse_paste(scr_stat *scp); 221static void draw_mouse_image(scr_stat *scp); 222static void remove_mouse_image(scr_stat *scp); 223static void draw_cutmarking(scr_stat *scp); 224static void remove_cutmarking(scr_stat *scp); 225static void save_palette(void); 226static void do_bell(scr_stat *scp, int pitch, int duration); 227static timeout_t blink_screen; 228#ifdef SC_SPLASH_SCREEN 229static void toggle_splash_screen(scr_stat *scp); 230#endif 231 232struct isa_driver scdriver = { 233 scprobe, scattach, "sc", 1 234}; 235 236static d_open_t scopen; 237static d_close_t scclose; 238static d_read_t scread; 239static d_write_t scwrite; 240static d_ioctl_t scioctl; 241static d_devtotty_t scdevtotty; 242static d_mmap_t scmmap; 243 244#define CDEV_MAJOR 12 245static struct cdevsw scdevsw = { 246 scopen, scclose, scread, scwrite, 247 scioctl, nullstop, noreset, scdevtotty, 248 ttselect, scmmap, nostrategy, "sc", NULL, -1 }; 249 250/* 251 * These functions need to be before calls to them so they can be inlined. 252 */ 253static inline void 254draw_cursor_image(scr_stat *scp) 255{ 256 u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf); 257 258 /* do we have a destructive cursor ? */ 259 if (flags & CHAR_CURSOR) { 260 cursor_image = *scp->cursor_pos; 261 scp->cursor_saveunder = cursor_image; 262 /* modify cursor_image */ 263 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ 264 set_destructive_cursor(scp); 265 cursor_image &= 0xff00; 266 cursor_image |= DEAD_CHAR; 267 } 268 } 269 else { 270 cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; 271 scp->cursor_saveunder = cursor_image; 272 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ 273 if ((cursor_image & 0x7000) == 0x7000) { 274 cursor_image &= 0x8fff; 275 if(!(cursor_image & 0x0700)) 276 cursor_image |= 0x0700; 277 } else { 278 cursor_image |= 0x7000; 279 if ((cursor_image & 0x0700) == 0x0700) 280 cursor_image &= 0xf0ff; 281 } 282 } 283 } 284 *ptr = cursor_image; 285} 286 287static inline void 288remove_cursor_image(scr_stat *scp) 289{ 290 *(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder; 291} 292 293static inline void 294move_crsr(scr_stat *scp, int x, int y) 295{ 296 if (x < 0) 297 x = 0; 298 if (y < 0) 299 y = 0; 300 if (x >= scp->xsize) 301 x = scp->xsize-1; 302 if (y >= scp->ysize) 303 y = scp->ysize-1; 304 scp->xpos = x; 305 scp->ypos = y; 306 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 307} 308 309static int 310scprobe(struct isa_device *dev) 311{ 312 if (!scvidprobe(dev->id_unit, dev->id_flags)) { 313 if (bootverbose) 314 printf("sc%d: no video adapter is found.\n", dev->id_unit); 315 return (0); 316 } 317 318 sc_port = dev->id_iobase; 319 if (sckbdprobe(dev->id_unit, dev->id_flags)) 320 return (IO_KBDSIZE); 321 else 322 return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); 323} 324 325/* probe video adapters, return TRUE if found */ 326static int 327scvidprobe(int unit, int flags) 328{ 329 /* 330 * XXX don't try to `printf' anything here, the console may not have 331 * been configured yet. 332 */ 333 u_short volatile *cp; 334 u_short was; 335 u_long pa; 336 u_long segoff; 337 338 /* do this test only once */ 339 if (init_done != COLD) 340 return (Crtat != 0); 341 342 /* 343 * Finish defaulting crtc variables for a mono screen. Crtat is a 344 * bogus common variable so that it can be shared with pcvt, so it 345 * can't be statically initialized. XXX. 346 */ 347 Crtat = (u_short *)MONO_BUF; 348 crtc_type = KD_MONO; 349 /* If CGA memory seems to work, switch to color. */ 350 cp = (u_short *)CGA_BUF; 351 was = *cp; 352 *cp = (u_short) 0xA55A; 353 if (*cp == 0xA55A) { 354 Crtat = (u_short *)CGA_BUF; 355 crtc_addr = COLOR_BASE; 356 crtc_type = KD_CGA; 357 } else { 358 cp = Crtat; 359 was = *cp; 360 *cp = (u_short) 0xA55A; 361 if (*cp != 0xA55A) { 362 /* no screen at all, bail out */ 363 Crtat = 0; 364 return FALSE; 365 } 366 } 367 *cp = was; 368 369 /* 370 * Check rtc and BIOS date area. 371 * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy 372 * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are 373 * zeros for EGA and VGA. However, the EGA/VGA BIOS will set 374 * these bits in BIOSDATA_EQUIPMENT according to the monitor 375 * type detected. 376 */ 377 switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ 378 case 0: /* EGA/VGA, or nothing */ 379 crtc_type = KD_EGA; 380 /* the color adapter may be in the 40x25 mode... XXX */ 381 break; 382 case 1: /* CGA 40x25 */ 383 /* switch to the 80x25 mode? XXX */ 384 /* FALL THROUGH */ 385 case 2: /* CGA 80x25 */ 386 /* `crtc_type' has already been set... */ 387 /* crtc_type = KD_CGA; */ 388 break; 389 case 3: /* MDA */ 390 /* `crtc_type' has already been set... */ 391 /* crtc_type = KD_MONO; */ 392 break; 393 } 394 395 /* is this a VGA or higher ? */ 396 outb(crtc_addr, 7); 397 if (inb(crtc_addr) == 7) { 398 399 crtc_type = KD_VGA; 400 crtc_vga = TRUE; 401 read_vgaregs(vgaregs); 402 403 /* Get the BIOS video mode pointer */ 404 segoff = *(u_long *)pa_to_va(0x4a8); 405 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 406 if (ISMAPPED(pa, sizeof(u_long))) { 407 segoff = *(u_long *)pa_to_va(pa); 408 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 409 if (ISMAPPED(pa, 64)) 410 video_mode_ptr = (char *)pa_to_va(pa); 411 } 412 } 413 414 return TRUE; 415} 416 417/* probe the keyboard, return TRUE if found */ 418static int 419sckbdprobe(int unit, int flags) 420{ 421 int codeset; 422 int c = -1; 423 int m; 424 425 sc_kbdc = kbdc_open(sc_port); 426 427 if (!kbdc_lock(sc_kbdc, TRUE)) { 428 /* driver error? */ 429 printf("sc%d: unable to lock the controller.\n", unit); 430 return ((flags & DETECT_KBD) ? FALSE : TRUE); 431 } 432 433 /* discard anything left after UserConfig */ 434 empty_both_buffers(sc_kbdc, 10); 435 436 /* save the current keyboard controller command byte */ 437 m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; 438 c = get_controller_command_byte(sc_kbdc); 439 if (c == -1) { 440 /* CONTROLLER ERROR */ 441 printf("sc%d: unable to get the current command byte value.\n", unit); 442 goto fail; 443 } 444 if (bootverbose) 445 printf("sc%d: the current keyboard controller command byte %04x\n", 446 unit, c); 447#if 0 448 /* override the keyboard lock switch */ 449 c |= KBD_OVERRIDE_KBD_LOCK; 450#endif 451 452 /* 453 * The keyboard may have been screwed up by the boot block. 454 * We may just be able to recover from error by testing the controller 455 * and the keyboard port. The controller command byte needs to be saved 456 * before this recovery operation, as some controllers seem to set 457 * the command byte to particular values. 458 */ 459 test_controller(sc_kbdc); 460 test_kbd_port(sc_kbdc); 461 462 /* enable the keyboard port, but disable the keyboard intr. */ 463 if (!set_controller_command_byte(sc_kbdc, 464 KBD_KBD_CONTROL_BITS, 465 KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { 466 /* CONTROLLER ERROR 467 * there is very little we can do... 468 */ 469 printf("sc%d: unable to set the command byte.\n", unit); 470 goto fail; 471 } 472 473 /* 474 * Check if we have an XT keyboard before we attempt to reset it. 475 * The procedure assumes that the keyboard and the controller have 476 * been set up properly by BIOS and have not been messed up 477 * during the boot process. 478 */ 479 codeset = -1; 480 if (flags & XT_KEYBD) 481 /* the user says there is a XT keyboard */ 482 codeset = 1; 483#ifdef DETECT_XT_KEYBOARD 484 else if ((c & KBD_TRANSLATION) == 0) { 485 /* SET_SCANCODE_SET is not always supported; ignore error */ 486 if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) 487 == KBD_ACK) 488 codeset = read_kbd_data(sc_kbdc); 489 } 490 if (bootverbose) 491 printf("sc%d: keyboard scancode set %d\n", unit, codeset); 492#endif /* DETECT_XT_KEYBOARD */ 493 494 /* reset keyboard hardware */ 495 if (!reset_kbd(sc_kbdc)) { 496 /* KEYBOARD ERROR 497 * Keyboard reset may fail either because the keyboard doen't exist, 498 * or because the keyboard doesn't pass the self-test, or the keyboard 499 * controller on the motherboard and the keyboard somehow fail to 500 * shake hands. It is just possible, particularly in the last case, 501 * that the keyoard controller may be left in a hung state. 502 * test_controller() and test_kbd_port() appear to bring the keyboard 503 * controller back (I don't know why and how, though.) 504 */ 505 empty_both_buffers(sc_kbdc, 10); 506 test_controller(sc_kbdc); 507 test_kbd_port(sc_kbdc); 508 /* We could disable the keyboard port and interrupt... but, 509 * the keyboard may still exist (see above). 510 */ 511 if (bootverbose) 512 printf("sc%d: failed to reset the keyboard.\n", unit); 513 goto fail; 514 } 515 516 /* 517 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards 518 * such as those on the IBM ThinkPad laptop computers can be used 519 * with the standard console driver. 520 */ 521 if (codeset == 1) { 522 if (send_kbd_command_and_data( 523 sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 524 /* XT kbd doesn't need scan code translation */ 525 c &= ~KBD_TRANSLATION; 526 } else { 527 /* KEYBOARD ERROR 528 * The XT kbd isn't usable unless the proper scan code set 529 * is selected. 530 */ 531 printf("sc%d: unable to set the XT keyboard mode.\n", unit); 532 goto fail; 533 } 534 } 535 /* enable the keyboard port and intr. */ 536 if (!set_controller_command_byte(sc_kbdc, 537 KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 538 (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 539 | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 540 /* CONTROLLER ERROR 541 * This is serious; we are left with the disabled keyboard intr. 542 */ 543 printf("sc%d: unable to enable the keyboard port and intr.\n", unit); 544 goto fail; 545 } 546 547succeed: 548 kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), 549 kbdc_lock(sc_kbdc, FALSE); 550 return TRUE; 551 552fail: 553 if (c != -1) 554 /* try to restore the command byte as before, if possible */ 555 set_controller_command_byte(sc_kbdc, 0xff, c); 556 kbdc_set_device_mask(sc_kbdc, 557 (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); 558 kbdc_lock(sc_kbdc, FALSE); 559 return FALSE; 560} 561 562#if NAPM > 0 563static int 564scresume(void *dummy) 565{ 566 shfts = ctls = alts = agrs = metas = 0; 567 return 0; 568} 569#endif 570 571static int 572scattach(struct isa_device *dev) 573{ 574 scr_stat *scp; 575 dev_t cdev = makedev(CDEV_MAJOR, 0); 576#ifdef DEVFS 577 int vc; 578#endif 579 580 scinit(); 581 flags = dev->id_flags; 582 583 scp = console[0]; 584 585 if (crtc_vga) { 586 cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 587 } 588 589 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 590 M_DEVBUF, M_NOWAIT); 591 592 /* copy temporary buffer to final buffer */ 593 bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); 594 595 scp->cursor_pos = scp->cursor_oldpos = 596 scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 597 scp->mouse_pos = scp->mouse_oldpos = 598 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 599 scp->mouse_xpos/8); 600 601 /* initialize history buffer & pointers */ 602 scp->history_head = scp->history_pos = scp->history = 603 (u_short *)malloc(scp->history_size*sizeof(u_short), 604 M_DEVBUF, M_NOWAIT); 605 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 606 607 /* initialize cursor stuff */ 608 if (!(scp->status & UNKNOWN_MODE)) { 609 draw_cursor_image(scp); 610 if (crtc_vga && (flags & CHAR_CURSOR)) 611 set_destructive_cursor(scp); 612 } 613 614 /* get screen update going */ 615 scrn_timer(NULL); 616 617 update_leds(scp->status); 618 619 if (bootverbose) { 620 printf("sc%d: BIOS video mode:%d\n", 621 dev->id_unit, *(u_char *)pa_to_va(0x449)); 622 printf("sc%d: VGA registers upon power-up\n", dev->id_unit); 623 dump_vgaregs(vgaregs); 624 printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode); 625 if (video_mode_ptr != NULL) { 626 printf("sc%d: VGA registers for mode:%d\n", 627 dev->id_unit, scp->mode); 628 dump_vgaregs(video_mode_ptr + (64*scp->mode)); 629 } 630 } 631 632 printf("sc%d: ", dev->id_unit); 633 switch(crtc_type) { 634 case KD_VGA: 635 if (crtc_addr == MONO_BASE) 636 printf("VGA mono"); 637 else 638 printf("VGA color"); 639 break; 640 case KD_EGA: 641 if (crtc_addr == MONO_BASE) 642 printf("EGA mono"); 643 else 644 printf("EGA color"); 645 break; 646 case KD_CGA: 647 printf("CGA"); 648 break; 649 case KD_MONO: 650 case KD_HERCULES: 651 default: 652 printf("MDA/hercules"); 653 break; 654 } 655 printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); 656 657#if NAPM > 0 658 scp->r_hook.ah_fun = scresume; 659 scp->r_hook.ah_arg = NULL; 660 scp->r_hook.ah_name = "system keyboard"; 661 scp->r_hook.ah_order = APM_MID_ORDER; 662 apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 663#endif 664 665 cdevsw_add(&cdev, &scdevsw, NULL); 666 667#ifdef DEVFS 668 for (vc = 0; vc < MAXCONS; vc++) 669 sc_devfs_token[vc] = devfs_add_devswf(&scdevsw, vc, DV_CHR, UID_ROOT, 670 GID_WHEEL, 0600, "ttyv%n", vc); 671#endif 672 return 0; 673} 674 675struct tty 676*scdevtotty(dev_t dev) 677{ 678 int unit = minor(dev); 679 680 if (init_done == COLD) 681 return(NULL); 682 if (unit == SC_CONSOLE) 683 return CONSOLE_TTY; 684 if (unit == SC_MOUSE) 685 return MOUSE_TTY; 686 if (unit >= MAXCONS || unit < 0) 687 return(NULL); 688 return VIRTUAL_TTY(unit); 689} 690 691int 692scopen(dev_t dev, int flag, int mode, struct proc *p) 693{ 694 struct tty *tp = scdevtotty(dev); 695 696 if (!tp) 697 return(ENXIO); 698 699 tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; 700 tp->t_param = scparam; 701 tp->t_dev = dev; 702 if (!(tp->t_state & TS_ISOPEN)) { 703 ttychars(tp); 704 /* Use the current setting of the <-- key as default VERASE. */ 705 /* If the Delete key is preferable, an stty is necessary */ 706 tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; 707 tp->t_iflag = TTYDEF_IFLAG; 708 tp->t_oflag = TTYDEF_OFLAG; 709 tp->t_cflag = TTYDEF_CFLAG; 710 tp->t_lflag = TTYDEF_LFLAG; 711 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 712 scparam(tp, &tp->t_termios); 713 ttsetwater(tp); 714 (*linesw[tp->t_line].l_modem)(tp, 1); 715 } 716 else 717 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 718 return(EBUSY); 719 if (minor(dev) < MAXCONS && !console[minor(dev)]) { 720 console[minor(dev)] = alloc_scp(); 721 } 722 if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 723 tp->t_winsize.ws_col = console[minor(dev)]->xsize; 724 tp->t_winsize.ws_row = console[minor(dev)]->ysize; 725 } 726 return ((*linesw[tp->t_line].l_open)(dev, tp)); 727} 728 729int 730scclose(dev_t dev, int flag, int mode, struct proc *p) 731{ 732 struct tty *tp = scdevtotty(dev); 733 struct scr_stat *scp; 734 735 if (!tp) 736 return(ENXIO); 737 if (minor(dev) < MAXCONS) { 738 scp = get_scr_stat(tp->t_dev); 739 if (scp->status & SWITCH_WAIT_ACQ) 740 wakeup((caddr_t)&scp->smode); 741#if not_yet_done 742 if (scp == &main_console) { 743 scp->pid = 0; 744 scp->proc = NULL; 745 scp->smode.mode = VT_AUTO; 746 } 747 else { 748 free(scp->scr_buf, M_DEVBUF); 749 free(scp->history, M_DEVBUF); 750 free(scp, M_DEVBUF); 751 console[minor(dev)] = NULL; 752 } 753#else 754 scp->pid = 0; 755 scp->proc = NULL; 756 scp->smode.mode = VT_AUTO; 757#endif 758 } 759 spltty(); 760 (*linesw[tp->t_line].l_close)(tp, flag); 761 ttyclose(tp); 762 spl0(); 763 return(0); 764} 765 766int 767scread(dev_t dev, struct uio *uio, int flag) 768{ 769 struct tty *tp = scdevtotty(dev); 770 771 if (!tp) 772 return(ENXIO); 773 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 774} 775 776int 777scwrite(dev_t dev, struct uio *uio, int flag) 778{ 779 struct tty *tp = scdevtotty(dev); 780 781 if (!tp) 782 return(ENXIO); 783 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 784} 785 786void 787scintr(int unit) 788{ 789 static struct tty *cur_tty; 790 int c, len; 791 u_char *cp; 792 793 /* make screensaver happy */ 794 scrn_time_stamp = time.tv_sec; 795 if (scrn_blanked) { 796 (*current_saver)(FALSE); 797 mark_all(cur_console); 798 } 799 800 /* 801 * Loop while there is still input to get from the keyboard. 802 * I don't think this is nessesary, and it doesn't fix 803 * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 804 */ 805 while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { 806 807 cur_tty = VIRTUAL_TTY(get_scr_num()); 808 if (!(cur_tty->t_state & TS_ISOPEN)) 809 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 810 continue; 811 812 switch (c & 0xff00) { 813 case 0x0000: /* normal key */ 814 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 815 break; 816 case FKEY: /* function key, return string */ 817 if (cp = get_fstr((u_int)c, (u_int *)&len)) { 818 while (len-- > 0) 819 (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 820 } 821 break; 822 case MKEY: /* meta is active, prepend ESC */ 823 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 824 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 825 break; 826 case BKEY: /* backtab fixed sequence (esc [ Z) */ 827 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 828 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 829 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 830 break; 831 } 832 } 833 834 if (cur_console->status & MOUSE_ENABLED) { 835 cur_console->status &= ~MOUSE_VISIBLE; 836 remove_mouse_image(cur_console); 837 } 838} 839 840static int 841scparam(struct tty *tp, struct termios *t) 842{ 843 tp->t_ispeed = t->c_ispeed; 844 tp->t_ospeed = t->c_ospeed; 845 tp->t_cflag = t->c_cflag; 846 return 0; 847} 848 849int 850scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 851{ 852 int error; 853 u_int i; 854 struct tty *tp; 855 scr_stat *scp; 856 857 tp = scdevtotty(dev); 858 if (!tp) 859 return ENXIO; 860 scp = get_scr_stat(tp->t_dev); 861 862 /* If there is a user_ioctl function call that first */ 863 if (sc_user_ioctl) { 864 if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p)) 865 return error; 866 } 867 868 switch (cmd) { /* process console hardware related ioctl's */ 869 870 case GIO_ATTR: /* get current attributes */ 871 *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 872 return 0; 873 874 case GIO_COLOR: /* is this a color console ? */ 875 if (crtc_addr == COLOR_BASE) 876 *(int*)data = 1; 877 else 878 *(int*)data = 0; 879 return 0; 880 881 case CONS_CURRENT: /* get current adapter type */ 882 *(int *)data = crtc_type; 883 return 0; 884 885 case CONS_GET: /* get current video mode */ 886 *(int*)data = scp->mode; 887 return 0; 888 889 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 890 if (*(int *)data < 0) 891 return EINVAL; 892 scrn_blank_time = *(int*)data; 893 if ((scrn_blank_time == 0) && scrn_blanked) { 894 (*current_saver)(FALSE); 895 mark_all(cur_console); 896 } 897 return 0; 898 899 case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 900 if ((*(int*)data) & 0x01) 901 flags |= BLINK_CURSOR; 902 else 903 flags &= ~BLINK_CURSOR; 904 if ((*(int*)data) & 0x02) { 905 if (!crtc_vga) 906 return ENXIO; 907 flags |= CHAR_CURSOR; 908 set_destructive_cursor(scp); 909 } else 910 flags &= ~CHAR_CURSOR; 911 return 0; 912 913 case CONS_BELLTYPE: /* set bell type sound/visual */ 914 if (*data) 915 flags |= VISUAL_BELL; 916 else 917 flags &= ~VISUAL_BELL; 918 return 0; 919 920 case CONS_HISTORY: /* set history size */ 921 if (*data) { 922 free(scp->history, M_DEVBUF); 923 scp->history_size = *(int*)data; 924 if (scp->history_size < scp->ysize) 925 scp->history = NULL; 926 else { 927 scp->history_size *= scp->xsize; 928 scp->history_head = scp->history_pos = scp->history = 929 (u_short *)malloc(scp->history_size*sizeof(u_short), 930 M_DEVBUF, M_WAITOK); 931 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 932 } 933 return 0; 934 } 935 else 936 return EINVAL; 937 938 case CONS_MOUSECTL: /* control mouse arrow */ 939 { 940 mouse_info_t *mouse = (mouse_info_t*)data; 941 942 if (!crtc_vga) 943 return ENXIO; 944 945 switch (mouse->operation) { 946 case MOUSE_MODE: 947 if (ISSIGVALID(mouse->u.mode.signal)) { 948 scp->mouse_signal = mouse->u.mode.signal; 949 scp->mouse_proc = p; 950 scp->mouse_pid = p->p_pid; 951 } 952 else { 953 scp->mouse_signal = 0; 954 scp->mouse_proc = NULL; 955 scp->mouse_pid = 0; 956 } 957 break; 958 959 case MOUSE_SHOW: 960 if (!(scp->status & MOUSE_ENABLED)) { 961 scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); 962 scp->mouse_oldpos = scp->mouse_pos; 963 mark_all(scp); 964 } 965 else 966 return EINVAL; 967 break; 968 969 case MOUSE_HIDE: 970 if (scp->status & MOUSE_ENABLED) { 971 scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 972 mark_all(scp); 973 } 974 else 975 return EINVAL; 976 break; 977 978 case MOUSE_MOVEABS: 979 scp->mouse_xpos = mouse->u.data.x; 980 scp->mouse_ypos = mouse->u.data.y; 981 set_mouse_pos(scp); 982 break; 983 984 case MOUSE_MOVEREL: 985 scp->mouse_xpos += mouse->u.data.x; 986 scp->mouse_ypos += mouse->u.data.y; 987 set_mouse_pos(scp); 988 break; 989 990 case MOUSE_GETINFO: 991 mouse->u.data.x = scp->mouse_xpos; 992 mouse->u.data.y = scp->mouse_ypos; 993 mouse->u.data.buttons = scp->mouse_buttons; 994 break; 995 996 case MOUSE_ACTION: 997 /* this should maybe only be settable from /dev/consolectl SOS */ 998 /* send out mouse event on /dev/sysmouse */ 999 if (cur_console->status & MOUSE_ENABLED) 1000 cur_console->status |= MOUSE_VISIBLE; 1001 if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1002 u_char buf[5]; 1003 int i; 1004 1005 buf[0] = 0x80 | ((~mouse->u.data.buttons) & 0x07); 1006 buf[1] = (mouse->u.data.x & 0x1fe >> 1); 1007 buf[3] = (mouse->u.data.x & 0x1ff) - buf[1]; 1008 buf[2] = -(mouse->u.data.y & 0x1fe >> 1); 1009 buf[4] = -(mouse->u.data.y & 0x1ff) - buf[2]; 1010 for (i=0; i<5; i++) 1011 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); 1012 } 1013 cur_console->mouse_xpos += mouse->u.data.x; 1014 cur_console->mouse_ypos += mouse->u.data.y; 1015 if (cur_console->mouse_signal) { 1016 cur_console->mouse_buttons = mouse->u.data.buttons; 1017 /* has controlling process died? */ 1018 if (cur_console->mouse_proc && 1019 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1020 cur_console->mouse_signal = 0; 1021 cur_console->mouse_proc = NULL; 1022 cur_console->mouse_pid = 0; 1023 } 1024 else 1025 psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1026 } 1027 else { 1028 /* process button presses */ 1029 if (cur_console->mouse_buttons != mouse->u.data.buttons) { 1030 cur_console->mouse_buttons = mouse->u.data.buttons; 1031 if (!(cur_console->status & UNKNOWN_MODE)) { 1032 if (cur_console->mouse_buttons & LEFT_BUTTON) 1033 mouse_cut_start(cur_console); 1034 else 1035 mouse_cut_end(cur_console); 1036 if (cur_console->mouse_buttons & RIGHT_BUTTON || 1037 cur_console->mouse_buttons & MIDDLE_BUTTON) 1038 mouse_paste(cur_console); 1039 } 1040 } 1041 } 1042 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) 1043 set_mouse_pos(cur_console); 1044 break; 1045 1046 default: 1047 return EINVAL; 1048 } 1049 /* make screensaver happy */ 1050 scrn_time_stamp = time.tv_sec; 1051 if (scrn_blanked) { 1052 (*current_saver)(FALSE); 1053 mark_all(cur_console); 1054 } 1055 return 0; 1056 } 1057 1058 case CONS_GETINFO: /* get current (virtual) console info */ 1059 { 1060 vid_info_t *ptr = (vid_info_t*)data; 1061 if (ptr->size == sizeof(struct vid_info)) { 1062 ptr->m_num = get_scr_num(); 1063 ptr->mv_col = scp->xpos; 1064 ptr->mv_row = scp->ypos; 1065 ptr->mv_csz = scp->xsize; 1066 ptr->mv_rsz = scp->ysize; 1067 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 1068 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 1069 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 1070 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 1071 ptr->mv_grfc.fore = 0; /* not supported */ 1072 ptr->mv_grfc.back = 0; /* not supported */ 1073 ptr->mv_ovscan = scp->border; 1074 ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 1075 return 0; 1076 } 1077 return EINVAL; 1078 } 1079 1080 case CONS_GETVERS: /* get version number */ 1081 *(int*)data = 0x200; /* version 2.0 */ 1082 return 0; 1083 1084 /* VGA TEXT MODES */ 1085 case SW_VGA_C40x25: 1086 case SW_VGA_C80x25: case SW_VGA_M80x25: 1087 case SW_VGA_C80x30: case SW_VGA_M80x30: 1088 case SW_VGA_C80x50: case SW_VGA_M80x50: 1089 case SW_VGA_C80x60: case SW_VGA_M80x60: 1090 case SW_B40x25: case SW_C40x25: 1091 case SW_B80x25: case SW_C80x25: 1092 case SW_ENH_B40x25: case SW_ENH_C40x25: 1093 case SW_ENH_B80x25: case SW_ENH_C80x25: 1094 case SW_ENH_B80x43: case SW_ENH_C80x43: 1095 case SW_EGAMONO80x25: 1096 1097 if (!crtc_vga || video_mode_ptr == NULL) 1098 return ENXIO; 1099 switch (cmd & 0xff) { 1100 case M_VGA_C80x60: case M_VGA_M80x60: 1101 if (!(fonts_loaded & FONT_8)) 1102 return EINVAL; 1103 scp->xsize = 80; 1104 scp->ysize = 60; 1105 break; 1106 case M_VGA_C80x50: case M_VGA_M80x50: 1107 if (!(fonts_loaded & FONT_8)) 1108 return EINVAL; 1109 scp->xsize = 80; 1110 scp->ysize = 50; 1111 break; 1112 case M_ENH_B80x43: case M_ENH_C80x43: 1113 if (!(fonts_loaded & FONT_8)) 1114 return EINVAL; 1115 scp->xsize = 80; 1116 scp->ysize = 43; 1117 break; 1118 case M_VGA_C80x30: case M_VGA_M80x30: 1119 scp->xsize = 80; 1120 scp->ysize = 30; 1121 break; 1122 case M_ENH_C40x25: case M_ENH_B40x25: 1123 case M_ENH_C80x25: case M_ENH_B80x25: 1124 case M_EGAMONO80x25: 1125 if (!(fonts_loaded & FONT_14)) 1126 return EINVAL; 1127 /* FALL THROUGH */ 1128 default: 1129 if ((cmd & 0xff) > M_VGA_CG320) 1130 return EINVAL; 1131 else 1132 scp->xsize = *(video_mode_ptr+((cmd&0xff)*64)); 1133 scp->ysize = *(video_mode_ptr+((cmd&0xff)*64)+1)+1; 1134 break; 1135 } 1136 scp->mode = cmd & 0xff; 1137 free(scp->scr_buf, M_DEVBUF); 1138 scp->scr_buf = (u_short *) 1139 malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK); 1140 scp->cursor_pos = scp->cursor_oldpos = 1141 scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 1142 scp->mouse_pos = scp->mouse_oldpos = 1143 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 1144 scp->mouse_xpos/8); 1145 free(cut_buffer, M_DEVBUF); 1146 cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 1147 cut_buffer[0] = 0x00; 1148 if (scp == cur_console) 1149 set_mode(scp); 1150 scp->status &= ~UNKNOWN_MODE; 1151 clear_screen(scp); 1152 if (tp->t_winsize.ws_col != scp->xsize 1153 || tp->t_winsize.ws_row != scp->ysize) { 1154 tp->t_winsize.ws_col = scp->xsize; 1155 tp->t_winsize.ws_row = scp->ysize; 1156 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1157 } 1158 return 0; 1159 1160 /* GRAPHICS MODES */ 1161 case SW_BG320: case SW_BG640: 1162 case SW_CG320: case SW_CG320_D: case SW_CG640_E: 1163 case SW_CG640x350: case SW_ENH_CG640: 1164 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 1165 1166 if (!crtc_vga || video_mode_ptr == NULL) 1167 return ENXIO; 1168 scp->mode = cmd & 0xFF; 1169 scp->xpixel = (*(video_mode_ptr + (scp->mode*64))) * 8; 1170 scp->ypixel = (*(video_mode_ptr + (scp->mode*64) + 1) + 1) * 1171 (*(video_mode_ptr + (scp->mode*64) + 2)); 1172 if (scp == cur_console) 1173 set_mode(scp); 1174 scp->status |= UNKNOWN_MODE; /* graphics mode */ 1175 /* clear_graphics();*/ 1176 1177 if (tp->t_winsize.ws_xpixel != scp->xpixel 1178 || tp->t_winsize.ws_ypixel != scp->ypixel) { 1179 tp->t_winsize.ws_xpixel = scp->xpixel; 1180 tp->t_winsize.ws_ypixel = scp->ypixel; 1181 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1182 } 1183 return 0; 1184 1185 case VT_SETMODE: /* set screen switcher mode */ 1186 { 1187 struct vt_mode *mode; 1188 1189 mode = (struct vt_mode *)data; 1190 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && 1191 ISSIGVALID(mode->frsig)) { 1192 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 1193 if (scp->smode.mode == VT_PROCESS) { 1194 scp->proc = p; 1195 scp->pid = scp->proc->p_pid; 1196 } 1197 return 0; 1198 } else 1199 return EINVAL; 1200 } 1201 1202 case VT_GETMODE: /* get screen switcher mode */ 1203 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 1204 return 0; 1205 1206 case VT_RELDISP: /* screen switcher ioctl */ 1207 switch(*data) { 1208 case VT_FALSE: /* user refuses to release screen, abort */ 1209 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1210 old_scp->status &= ~SWITCH_WAIT_REL; 1211 switch_in_progress = FALSE; 1212 return 0; 1213 } 1214 return EINVAL; 1215 1216 case VT_TRUE: /* user has released screen, go on */ 1217 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1218 scp->status &= ~SWITCH_WAIT_REL; 1219 exchange_scr(); 1220 if (new_scp->smode.mode == VT_PROCESS) { 1221 new_scp->status |= SWITCH_WAIT_ACQ; 1222 psignal(new_scp->proc, new_scp->smode.acqsig); 1223 } 1224 else 1225 switch_in_progress = FALSE; 1226 return 0; 1227 } 1228 return EINVAL; 1229 1230 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 1231 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 1232 scp->status &= ~SWITCH_WAIT_ACQ; 1233 switch_in_progress = FALSE; 1234 return 0; 1235 } 1236 return EINVAL; 1237 1238 default: 1239 return EINVAL; 1240 } 1241 /* NOT REACHED */ 1242 1243 case VT_OPENQRY: /* return free virtual console */ 1244 for (i = 0; i < MAXCONS; i++) { 1245 tp = VIRTUAL_TTY(i); 1246 if (!(tp->t_state & TS_ISOPEN)) { 1247 *data = i + 1; 1248 return 0; 1249 } 1250 } 1251 return EINVAL; 1252 1253 case VT_ACTIVATE: /* switch to screen *data */ 1254 return switch_scr(scp, (*data) - 1); 1255 1256 case VT_WAITACTIVE: /* wait for switch to occur */ 1257 if (*data > MAXCONS || *data < 0) 1258 return EINVAL; 1259 if (minor(dev) == (*data) - 1) 1260 return 0; 1261 if (*data == 0) { 1262 if (scp == cur_console) 1263 return 0; 1264 } 1265 else 1266 scp = console[(*data) - 1]; 1267 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1268 "waitvt", 0)) == ERESTART) ; 1269 return error; 1270 1271 case VT_GETACTIVE: 1272 *data = get_scr_num()+1; 1273 return 0; 1274 1275 case KDENABIO: /* allow io operations */ 1276 error = suser(p->p_ucred, &p->p_acflag); 1277 if (error != 0) 1278 return error; 1279 if (securelevel > 0) 1280 return EPERM; 1281 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 1282 return 0; 1283 1284 case KDDISABIO: /* disallow io operations (default) */ 1285 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 1286 return 0; 1287 1288 case KDSETMODE: /* set current mode of this (virtual) console */ 1289 switch (*data) { 1290 case KD_TEXT: /* switch to TEXT (known) mode */ 1291 /* restore fonts & palette ! */ 1292 if (crtc_vga) { 1293 if (fonts_loaded & FONT_8) 1294 copy_font(LOAD, FONT_8, font_8); 1295 if (fonts_loaded & FONT_14) 1296 copy_font(LOAD, FONT_14, font_14); 1297 if (fonts_loaded & FONT_16) 1298 copy_font(LOAD, FONT_16, font_16); 1299 if (flags & CHAR_CURSOR) 1300 set_destructive_cursor(scp); 1301 load_palette(palette); 1302 } 1303 /* FALL THROUGH */ 1304 1305 case KD_TEXT1: /* switch to TEXT (known) mode */ 1306 /* no restore fonts & palette */ 1307 if (crtc_vga && video_mode_ptr) 1308 set_mode(scp); 1309 scp->status &= ~UNKNOWN_MODE; 1310 clear_screen(scp); 1311 return 0; 1312 1313 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 1314 scp->status |= UNKNOWN_MODE; 1315 return 0; 1316 default: 1317 return EINVAL; 1318 } 1319 /* NOT REACHED */ 1320 1321 case KDGETMODE: /* get current mode of this (virtual) console */ 1322 *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 1323 return 0; 1324 1325 case KDSBORDER: /* set border color of this (virtual) console */ 1326 if (!crtc_vga) 1327 return ENXIO; 1328 scp->border = *data; 1329 if (scp == cur_console) 1330 set_border(scp->border); 1331 return 0; 1332 1333 case KDSKBSTATE: /* set keyboard state (locks) */ 1334 if (*data >= 0 && *data <= LOCK_KEY_MASK) { 1335 scp->status &= ~LOCK_KEY_MASK; 1336 scp->status |= *data; 1337 if (scp == cur_console) 1338 update_leds(scp->status); 1339 return 0; 1340 } 1341 return EINVAL; 1342 1343 case KDGKBSTATE: /* get keyboard state (locks) */ 1344 *data = scp->status & LOCK_KEY_MASK; 1345 return 0; 1346 1347 case KDSETRAD: /* set keyboard repeat & delay rates */ 1348 if (*data & 0x80) 1349 return EINVAL; 1350 if (sc_kbdc != NULL) 1351 set_keyboard(KBDC_SET_TYPEMATIC, *data); 1352 return 0; 1353 1354 case KDSKBMODE: /* set keyboard mode */ 1355 switch (*data) { 1356 case K_RAW: /* switch to RAW scancode mode */ 1357 scp->status |= KBD_RAW_MODE; 1358 return 0; 1359 1360 case K_XLATE: /* switch to XLT ascii mode */ 1361 if (scp == cur_console && scp->status & KBD_RAW_MODE) 1362 shfts = ctls = alts = agrs = metas = 0; 1363 scp->status &= ~KBD_RAW_MODE; 1364 return 0; 1365 default: 1366 return EINVAL; 1367 } 1368 /* NOT REACHED */ 1369 1370 case KDGKBMODE: /* get keyboard mode */ 1371 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE; 1372 return 0; 1373 1374 case KDMKTONE: /* sound the bell */ 1375 if (*(int*)data) 1376 do_bell(scp, (*(int*)data)&0xffff, 1377 (((*(int*)data)>>16)&0xffff)*hz/1000); 1378 else 1379 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1380 return 0; 1381 1382 case KIOCSOUND: /* make tone (*data) hz */ 1383 if (scp == cur_console) { 1384 if (*(int*)data) { 1385 int pitch = timer_freq / *(int*)data; 1386 1387 /* set command for counter 2, 2 byte write */ 1388 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1389 return EBUSY; 1390 1391 /* set pitch */ 1392 outb(TIMER_CNTR2, pitch); 1393 outb(TIMER_CNTR2, (pitch>>8)); 1394 1395 /* enable counter 2 output to speaker */ 1396 outb(IO_PPI, inb(IO_PPI) | 3); 1397 } 1398 else { 1399 /* disable counter 2 output to speaker */ 1400 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1401 release_timer2(); 1402 } 1403 } 1404 return 0; 1405 1406 case KDGKBTYPE: /* get keyboard type */ 1407 *data = 0; /* type not known (yet) */ 1408 return 0; 1409 1410 case KDSETLED: /* set keyboard LED status */ 1411 if (*data >= 0 && *data <= LED_MASK) { 1412 scp->status &= ~LED_MASK; 1413 scp->status |= *data; 1414 if (scp == cur_console) 1415 update_leds(scp->status); 1416 return 0; 1417 } 1418 return EINVAL; 1419 1420 case KDGETLED: /* get keyboard LED status */ 1421 *data = scp->status & LED_MASK; 1422 return 0; 1423 1424 case GETFKEY: /* get functionkey string */ 1425 if (*(u_short*)data < n_fkey_tab) { 1426 fkeyarg_t *ptr = (fkeyarg_t*)data; 1427 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1428 fkey_tab[ptr->keynum].len); 1429 ptr->flen = fkey_tab[ptr->keynum].len; 1430 return 0; 1431 } 1432 else 1433 return EINVAL; 1434 1435 case SETFKEY: /* set functionkey string */ 1436 if (*(u_short*)data < n_fkey_tab) { 1437 fkeyarg_t *ptr = (fkeyarg_t*)data; 1438 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1439 min(ptr->flen, MAXFK)); 1440 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1441 return 0; 1442 } 1443 else 1444 return EINVAL; 1445 1446 case GIO_SCRNMAP: /* get output translation table */ 1447 bcopy(&scr_map, data, sizeof(scr_map)); 1448 return 0; 1449 1450 case PIO_SCRNMAP: /* set output translation table */ 1451 bcopy(data, &scr_map, sizeof(scr_map)); 1452 for (i=0; i<sizeof(scr_map); i++) 1453 scr_rmap[scr_map[i]] = i; 1454 return 0; 1455 1456 case GIO_KEYMAP: /* get keyboard translation table */ 1457 bcopy(&key_map, data, sizeof(key_map)); 1458 return 0; 1459 1460 case PIO_KEYMAP: /* set keyboard translation table */ 1461 bcopy(data, &key_map, sizeof(key_map)); 1462 return 0; 1463 1464 case PIO_FONT8x8: /* set 8x8 dot font */ 1465 if (!crtc_vga) 1466 return ENXIO; 1467 bcopy(data, font_8, 8*256); 1468 fonts_loaded |= FONT_8; 1469 copy_font(LOAD, FONT_8, font_8); 1470 if (flags & CHAR_CURSOR) 1471 set_destructive_cursor(scp); 1472 return 0; 1473 1474 case GIO_FONT8x8: /* get 8x8 dot font */ 1475 if (!crtc_vga) 1476 return ENXIO; 1477 if (fonts_loaded & FONT_8) { 1478 bcopy(font_8, data, 8*256); 1479 return 0; 1480 } 1481 else 1482 return ENXIO; 1483 1484 case PIO_FONT8x14: /* set 8x14 dot font */ 1485 if (!crtc_vga) 1486 return ENXIO; 1487 bcopy(data, font_14, 14*256); 1488 fonts_loaded |= FONT_14; 1489 copy_font(LOAD, FONT_14, font_14); 1490 if (flags & CHAR_CURSOR) 1491 set_destructive_cursor(scp); 1492 return 0; 1493 1494 case GIO_FONT8x14: /* get 8x14 dot font */ 1495 if (!crtc_vga) 1496 return ENXIO; 1497 if (fonts_loaded & FONT_14) { 1498 bcopy(font_14, data, 14*256); 1499 return 0; 1500 } 1501 else 1502 return ENXIO; 1503 1504 case PIO_FONT8x16: /* set 8x16 dot font */ 1505 if (!crtc_vga) 1506 return ENXIO; 1507 bcopy(data, font_16, 16*256); 1508 fonts_loaded |= FONT_16; 1509 copy_font(LOAD, FONT_16, font_16); 1510 if (flags & CHAR_CURSOR) 1511 set_destructive_cursor(scp); 1512 return 0; 1513 1514 case GIO_FONT8x16: /* get 8x16 dot font */ 1515 if (!crtc_vga) 1516 return ENXIO; 1517 if (fonts_loaded & FONT_16) { 1518 bcopy(font_16, data, 16*256); 1519 return 0; 1520 } 1521 else 1522 return ENXIO; 1523 default: 1524 break; 1525 } 1526 1527 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1528 if (error >= 0) 1529 return(error); 1530 error = ttioctl(tp, cmd, data, flag); 1531 if (error >= 0) 1532 return(error); 1533 return(ENOTTY); 1534} 1535 1536static void 1537scstart(struct tty *tp) 1538{ 1539 struct clist *rbp; 1540 int s, len; 1541 u_char buf[PCBURST]; 1542 scr_stat *scp = get_scr_stat(tp->t_dev); 1543 1544 if (scp->status & SLKED || blink_in_progress) 1545 return; /* XXX who repeats the call when the above flags are cleared? */ 1546 s = spltty(); 1547 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1548 tp->t_state |= TS_BUSY; 1549 rbp = &tp->t_outq; 1550 while (rbp->c_cc) { 1551 len = q_to_b(rbp, buf, PCBURST); 1552 splx(s); 1553 ansi_put(scp, buf, len); 1554 s = spltty(); 1555 } 1556 tp->t_state &= ~TS_BUSY; 1557 ttwwakeup(tp); 1558 } 1559 splx(s); 1560} 1561 1562static void 1563scmousestart(struct tty *tp) 1564{ 1565 struct clist *rbp; 1566 int s; 1567 u_char buf[PCBURST]; 1568 1569 s = spltty(); 1570 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1571 tp->t_state |= TS_BUSY; 1572 rbp = &tp->t_outq; 1573 while (rbp->c_cc) { 1574 q_to_b(rbp, buf, PCBURST); 1575 } 1576 tp->t_state &= ~TS_BUSY; 1577 ttwwakeup(tp); 1578 } 1579 splx(s); 1580} 1581 1582void 1583sccnprobe(struct consdev *cp) 1584{ 1585 struct isa_device *dvp; 1586 1587 /* 1588 * Take control if we are the highest priority enabled display device. 1589 */ 1590 dvp = find_display(); 1591 if (dvp == NULL || dvp->id_driver != &scdriver) { 1592 cp->cn_pri = CN_DEAD; 1593 return; 1594 } 1595 1596 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { 1597 cp->cn_pri = CN_DEAD; 1598 return; 1599 } 1600 1601 /* initialize required fields */ 1602 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 1603 cp->cn_pri = CN_INTERNAL; 1604 1605 sc_kbdc = kbdc_open(sc_port); 1606} 1607 1608void 1609sccninit(struct consdev *cp) 1610{ 1611 scinit(); 1612} 1613 1614void 1615sccnputc(dev_t dev, int c) 1616{ 1617 u_char buf[1]; 1618 int s; 1619 scr_stat *scp = console[0]; 1620 term_stat save = scp->term; 1621 1622 scp->term = kernel_console; 1623 current_default = &kernel_default; 1624 if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) 1625 remove_cursor_image(scp); 1626 buf[0] = c; 1627 ansi_put(scp, buf, 1); 1628 kernel_console = scp->term; 1629 current_default = &user_default; 1630 scp->term = save; 1631 s = splclock(); 1632 if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) { 1633 if (/* timer not running && */ (scp->start <= scp->end)) { 1634 sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, 1635 (1 + scp->end - scp->start) * sizeof(u_short)); 1636 scp->start = scp->xsize * scp->ysize; 1637 scp->end = 0; 1638 } 1639 scp->cursor_oldpos = scp->cursor_pos; 1640 draw_cursor_image(scp); 1641 } 1642 splx(s); 1643} 1644 1645int 1646sccngetc(dev_t dev) 1647{ 1648 int s = spltty(); /* block scintr while we poll */ 1649 int c = scgetc(SCGETC_CN); 1650 splx(s); 1651 return(c); 1652} 1653 1654int 1655sccncheckc(dev_t dev) 1656{ 1657 int c, s; 1658 1659 s = spltty(); 1660 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); 1661 splx(s); 1662 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ 1663} 1664 1665static scr_stat 1666*get_scr_stat(dev_t dev) 1667{ 1668 int unit = minor(dev); 1669 1670 if (unit == SC_CONSOLE) 1671 return console[0]; 1672 if (unit >= MAXCONS || unit < 0) 1673 return(NULL); 1674 return console[unit]; 1675} 1676 1677static int 1678get_scr_num() 1679{ 1680 int i = 0; 1681 1682 while ((i < MAXCONS) && (cur_console != console[i])) 1683 i++; 1684 return i < MAXCONS ? i : 0; 1685} 1686 1687static void 1688scrn_timer(void *arg) 1689{ 1690 scr_stat *scp = cur_console; 1691 int s = spltty(); 1692 1693 /* 1694 * With release 2.1 of the Xaccel server, the keyboard is left 1695 * hanging pretty often. Apparently an interrupt from the 1696 * keyboard is lost, and I don't know why (yet). 1697 * This ugly hack calls scintr if input is ready for the keyboard 1698 * and conveniently hides the problem. XXX 1699 */ 1700 /* Try removing anything stuck in the keyboard controller; whether 1701 * it's a keyboard scan code or mouse data. `scintr()' doesn't 1702 * read the mouse data directly, but `kbdio' routines will, as a 1703 * side effect. 1704 */ 1705 if (kbdc_lock(sc_kbdc, TRUE)) { 1706 /* 1707 * We have seen the lock flag is not set. Let's reset the flag early; 1708 * otherwise `update_led()' failes which may want the lock 1709 * during `scintr()'. 1710 */ 1711 kbdc_lock(sc_kbdc, FALSE); 1712 if (kbdc_data_ready(sc_kbdc)) 1713 scintr(0); 1714 } 1715 1716 /* should we just return ? */ 1717 if ((scp->status&UNKNOWN_MODE) || blink_in_progress || switch_in_progress) { 1718 timeout(scrn_timer, NULL, hz / 10); 1719 splx(s); 1720 return; 1721 } 1722 1723 if (!scrn_blanked) { 1724 /* update screen image */ 1725 if (scp->start <= scp->end) { 1726 sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, 1727 (1 + scp->end - scp->start) * sizeof(u_short)); 1728 } 1729 1730 /* update "pseudo" mouse pointer image */ 1731 if ((scp->status & MOUSE_VISIBLE) && crtc_vga) { 1732 /* did mouse move since last time ? */ 1733 if (scp->status & MOUSE_MOVED) { 1734 /* do we need to remove old mouse pointer image ? */ 1735 if (scp->mouse_cut_start != NULL || 1736 (scp->mouse_pos-scp->scr_buf) <= scp->start || 1737 (scp->mouse_pos+scp->xsize+1-scp->scr_buf) >= scp->end) { 1738 remove_mouse_image(scp); 1739 } 1740 scp->status &= ~MOUSE_MOVED; 1741 draw_mouse_image(scp); 1742 } 1743 else { 1744 /* mouse didn't move, has it been overwritten ? */ 1745 if ((scp->mouse_pos+scp->xsize+1-scp->scr_buf) >= scp->start && 1746 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 1747 draw_mouse_image(scp); 1748 } 1749 } 1750 } 1751 1752 /* update cursor image */ 1753 if (scp->status & CURSOR_ENABLED) { 1754 /* did cursor move since last time ? */ 1755 if (scp->cursor_pos != scp->cursor_oldpos) { 1756 /* do we need to remove old cursor image ? */ 1757 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 1758 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 1759 remove_cursor_image(scp); 1760 } 1761 scp->cursor_oldpos = scp->cursor_pos; 1762 draw_cursor_image(scp); 1763 } 1764 else { 1765 /* cursor didn't move, has it been overwritten ? */ 1766 if (scp->cursor_pos - scp->scr_buf >= scp->start && 1767 scp->cursor_pos - scp->scr_buf <= scp->end) { 1768 draw_cursor_image(scp); 1769 } else { 1770 /* if its a blinking cursor, we may have to update it */ 1771 if (flags & BLINK_CURSOR) 1772 draw_cursor_image(scp); 1773 } 1774 } 1775 blinkrate++; 1776 } 1777 1778 if (scp->mouse_cut_start != NULL) 1779 draw_cutmarking(scp); 1780 1781 scp->end = 0; 1782 scp->start = scp->xsize*scp->ysize; 1783 } 1784 if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time)) 1785 (*current_saver)(TRUE); 1786 timeout(scrn_timer, NULL, hz / 25); 1787 splx(s); 1788} 1789 1790static void 1791clear_screen(scr_stat *scp) 1792{ 1793 move_crsr(scp, 0, 0); 1794 scp->cursor_oldpos = scp->cursor_pos; 1795 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 1796 scp->xsize * scp->ysize); 1797 mark_all(scp); 1798 remove_cutmarking(scp); 1799} 1800 1801static int 1802switch_scr(scr_stat *scp, u_int next_scr) 1803{ 1804 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 1805 switch_in_progress = FALSE; 1806 1807 if (next_scr >= MAXCONS || switch_in_progress || 1808 (cur_console->smode.mode == VT_AUTO 1809 && cur_console->status & UNKNOWN_MODE)) { 1810 do_bell(scp, BELL_PITCH, BELL_DURATION); 1811 return EINVAL; 1812 } 1813 1814 /* is the wanted virtual console open ? */ 1815 if (next_scr) { 1816 struct tty *tp = VIRTUAL_TTY(next_scr); 1817 if (!(tp->t_state & TS_ISOPEN)) { 1818 do_bell(scp, BELL_PITCH, BELL_DURATION); 1819 return EINVAL; 1820 } 1821 } 1822 /* delay switch if actively updating screen */ 1823 if (write_in_progress || blink_in_progress) { 1824 delayed_next_scr = next_scr+1; 1825 return 0; 1826 } 1827 switch_in_progress = TRUE; 1828 old_scp = cur_console; 1829 new_scp = console[next_scr]; 1830 wakeup((caddr_t)&new_scp->smode); 1831 if (new_scp == old_scp) { 1832 switch_in_progress = FALSE; 1833 delayed_next_scr = FALSE; 1834 return 0; 1835 } 1836 1837 /* has controlling process died? */ 1838 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1839 old_scp->smode.mode = VT_AUTO; 1840 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1841 new_scp->smode.mode = VT_AUTO; 1842 1843 /* check the modes and switch appropriately */ 1844 if (old_scp->smode.mode == VT_PROCESS) { 1845 old_scp->status |= SWITCH_WAIT_REL; 1846 psignal(old_scp->proc, old_scp->smode.relsig); 1847 } 1848 else { 1849 exchange_scr(); 1850 if (new_scp->smode.mode == VT_PROCESS) { 1851 new_scp->status |= SWITCH_WAIT_ACQ; 1852 psignal(new_scp->proc, new_scp->smode.acqsig); 1853 } 1854 else 1855 switch_in_progress = FALSE; 1856 } 1857 return 0; 1858} 1859 1860static void 1861exchange_scr(void) 1862{ 1863 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1864 cur_console = new_scp; 1865 if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ 1866 if (crtc_vga && video_mode_ptr) 1867 set_mode(new_scp); 1868 } 1869 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1870 if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) { 1871 if (flags & CHAR_CURSOR) 1872 set_destructive_cursor(new_scp); 1873 load_palette(palette); 1874 } 1875 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1876 shfts = ctls = alts = agrs = metas = 0; 1877 update_leds(new_scp->status); 1878 delayed_next_scr = FALSE; 1879 mark_all(new_scp); 1880} 1881 1882static void 1883scan_esc(scr_stat *scp, u_char c) 1884{ 1885 static u_char ansi_col[16] = 1886 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1887 int i, n; 1888 u_short *src, *dst, count; 1889 1890 if (scp->term.esc == 1) { 1891 switch (c) { 1892 1893 case '7': /* Save cursor position */ 1894 scp->saved_xpos = scp->xpos; 1895 scp->saved_ypos = scp->ypos; 1896 break; 1897 1898 case '8': /* Restore saved cursor position */ 1899 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 1900 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 1901 break; 1902 1903 case '[': /* Start ESC [ sequence */ 1904 scp->term.esc = 2; 1905 scp->term.last_param = -1; 1906 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1907 scp->term.param[i] = 1; 1908 scp->term.num_param = 0; 1909 return; 1910 1911 case 'M': /* Move cursor up 1 line, scroll if at top */ 1912 if (scp->ypos > 0) 1913 move_crsr(scp, scp->xpos, scp->ypos - 1); 1914 else { 1915 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 1916 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 1917 fillw(scp->term.cur_color | scr_map[0x20], 1918 scp->scr_buf, scp->xsize); 1919 mark_all(scp); 1920 } 1921 break; 1922#if notyet 1923 case 'Q': 1924 scp->term.esc = 4; 1925 break; 1926#endif 1927 case 'c': /* Clear screen & home */ 1928 clear_screen(scp); 1929 break; 1930 } 1931 } 1932 else if (scp->term.esc == 2) { 1933 if (c >= '0' && c <= '9') { 1934 if (scp->term.num_param < MAX_ESC_PAR) { 1935 if (scp->term.last_param != scp->term.num_param) { 1936 scp->term.last_param = scp->term.num_param; 1937 scp->term.param[scp->term.num_param] = 0; 1938 } 1939 else 1940 scp->term.param[scp->term.num_param] *= 10; 1941 scp->term.param[scp->term.num_param] += c - '0'; 1942 return; 1943 } 1944 } 1945 scp->term.num_param = scp->term.last_param + 1; 1946 switch (c) { 1947 1948 case ';': 1949 if (scp->term.num_param < MAX_ESC_PAR) 1950 return; 1951 break; 1952 1953 case '=': 1954 scp->term.esc = 3; 1955 scp->term.last_param = -1; 1956 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1957 scp->term.param[i] = 1; 1958 scp->term.num_param = 0; 1959 return; 1960 1961 case 'A': /* up n rows */ 1962 n = scp->term.param[0]; if (n < 1) n = 1; 1963 move_crsr(scp, scp->xpos, scp->ypos - n); 1964 break; 1965 1966 case 'B': /* down n rows */ 1967 n = scp->term.param[0]; if (n < 1) n = 1; 1968 move_crsr(scp, scp->xpos, scp->ypos + n); 1969 break; 1970 1971 case 'C': /* right n columns */ 1972 n = scp->term.param[0]; if (n < 1) n = 1; 1973 move_crsr(scp, scp->xpos + n, scp->ypos); 1974 break; 1975 1976 case 'D': /* left n columns */ 1977 n = scp->term.param[0]; if (n < 1) n = 1; 1978 move_crsr(scp, scp->xpos - n, scp->ypos); 1979 break; 1980 1981 case 'E': /* cursor to start of line n lines down */ 1982 n = scp->term.param[0]; if (n < 1) n = 1; 1983 move_crsr(scp, 0, scp->ypos + n); 1984 break; 1985 1986 case 'F': /* cursor to start of line n lines up */ 1987 n = scp->term.param[0]; if (n < 1) n = 1; 1988 move_crsr(scp, 0, scp->ypos - n); 1989 break; 1990 1991 case 'f': /* Cursor move */ 1992 case 'H': 1993 if (scp->term.num_param == 0) 1994 move_crsr(scp, 0, 0); 1995 else if (scp->term.num_param == 2) 1996 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 1997 break; 1998 1999 case 'J': /* Clear all or part of display */ 2000 if (scp->term.num_param == 0) 2001 n = 0; 2002 else 2003 n = scp->term.param[0]; 2004 switch (n) { 2005 case 0: /* clear form cursor to end of display */ 2006 fillw(scp->term.cur_color | scr_map[0x20], 2007 scp->cursor_pos, 2008 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2009 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2010 mark_for_update(scp, scp->xsize * scp->ysize); 2011 remove_cutmarking(scp); 2012 break; 2013 case 1: /* clear from beginning of display to cursor */ 2014 fillw(scp->term.cur_color | scr_map[0x20], 2015 scp->scr_buf, 2016 scp->cursor_pos - scp->scr_buf); 2017 mark_for_update(scp, 0); 2018 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2019 remove_cutmarking(scp); 2020 break; 2021 case 2: /* clear entire display */ 2022 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2023 scp->xsize * scp->ysize); 2024 mark_all(scp); 2025 remove_cutmarking(scp); 2026 break; 2027 } 2028 break; 2029 2030 case 'K': /* Clear all or part of line */ 2031 if (scp->term.num_param == 0) 2032 n = 0; 2033 else 2034 n = scp->term.param[0]; 2035 switch (n) { 2036 case 0: /* clear form cursor to end of line */ 2037 fillw(scp->term.cur_color | scr_map[0x20], 2038 scp->cursor_pos, 2039 scp->xsize - scp->xpos); 2040 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2041 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2042 scp->xsize - scp->xpos); 2043 break; 2044 case 1: /* clear from beginning of line to cursor */ 2045 fillw(scp->term.cur_color | scr_map[0x20], 2046 scp->cursor_pos - scp->xpos, 2047 scp->xpos + 1); 2048 mark_for_update(scp, scp->ypos * scp->xsize); 2049 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2050 break; 2051 case 2: /* clear entire line */ 2052 fillw(scp->term.cur_color | scr_map[0x20], 2053 scp->cursor_pos - scp->xpos, 2054 scp->xsize); 2055 mark_for_update(scp, scp->ypos * scp->xsize); 2056 mark_for_update(scp, (scp->ypos + 1) * scp->xsize); 2057 break; 2058 } 2059 break; 2060 2061 case 'L': /* Insert n lines */ 2062 n = scp->term.param[0]; if (n < 1) n = 1; 2063 if (n > scp->ysize - scp->ypos) 2064 n = scp->ysize - scp->ypos; 2065 src = scp->scr_buf + scp->ypos * scp->xsize; 2066 dst = src + n * scp->xsize; 2067 count = scp->ysize - (scp->ypos + n); 2068 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2069 fillw(scp->term.cur_color | scr_map[0x20], src, 2070 n * scp->xsize); 2071 mark_for_update(scp, scp->ypos * scp->xsize); 2072 mark_for_update(scp, scp->xsize * scp->ysize); 2073 break; 2074 2075 case 'M': /* Delete n lines */ 2076 n = scp->term.param[0]; if (n < 1) n = 1; 2077 if (n > scp->ysize - scp->ypos) 2078 n = scp->ysize - scp->ypos; 2079 dst = scp->scr_buf + scp->ypos * scp->xsize; 2080 src = dst + n * scp->xsize; 2081 count = scp->ysize - (scp->ypos + n); 2082 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2083 src = dst + count * scp->xsize; 2084 fillw(scp->term.cur_color | scr_map[0x20], src, 2085 n * scp->xsize); 2086 mark_for_update(scp, scp->ypos * scp->xsize); 2087 mark_for_update(scp, scp->xsize * scp->ysize); 2088 break; 2089 2090 case 'P': /* Delete n chars */ 2091 n = scp->term.param[0]; if (n < 1) n = 1; 2092 if (n > scp->xsize - scp->xpos) 2093 n = scp->xsize - scp->xpos; 2094 dst = scp->cursor_pos; 2095 src = dst + n; 2096 count = scp->xsize - (scp->xpos + n); 2097 bcopy(src, dst, count * sizeof(u_short)); 2098 src = dst + count; 2099 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2100 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2101 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 2102 break; 2103 2104 case '@': /* Insert n chars */ 2105 n = scp->term.param[0]; if (n < 1) n = 1; 2106 if (n > scp->xsize - scp->xpos) 2107 n = scp->xsize - scp->xpos; 2108 src = scp->cursor_pos; 2109 dst = src + n; 2110 count = scp->xsize - (scp->xpos + n); 2111 bcopy(src, dst, count * sizeof(u_short)); 2112 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2113 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2114 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 2115 break; 2116 2117 case 'S': /* scroll up n lines */ 2118 n = scp->term.param[0]; if (n < 1) n = 1; 2119 if (n > scp->ysize) 2120 n = scp->ysize; 2121 bcopy(scp->scr_buf + (scp->xsize * n), 2122 scp->scr_buf, 2123 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2124 fillw(scp->term.cur_color | scr_map[0x20], 2125 scp->scr_buf + scp->xsize * (scp->ysize - n), 2126 scp->xsize * n); 2127 mark_all(scp); 2128 break; 2129 2130 case 'T': /* scroll down n lines */ 2131 n = scp->term.param[0]; if (n < 1) n = 1; 2132 if (n > scp->ysize) 2133 n = scp->ysize; 2134 bcopy(scp->scr_buf, 2135 scp->scr_buf + (scp->xsize * n), 2136 scp->xsize * (scp->ysize - n) * 2137 sizeof(u_short)); 2138 fillw(scp->term.cur_color | scr_map[0x20], 2139 scp->scr_buf, scp->xsize * n); 2140 mark_all(scp); 2141 break; 2142 2143 case 'X': /* erase n characters in line */ 2144 n = scp->term.param[0]; if (n < 1) n = 1; 2145 if (n > scp->xsize - scp->xpos) 2146 n = scp->xsize - scp->xpos; 2147 fillw(scp->term.cur_color | scr_map[0x20], 2148 scp->cursor_pos, n); 2149 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2150 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n); 2151 break; 2152 2153 case 'Z': /* move n tabs backwards */ 2154 n = scp->term.param[0]; if (n < 1) n = 1; 2155 if ((i = scp->xpos & 0xf8) == scp->xpos) 2156 i -= 8*n; 2157 else 2158 i -= 8*(n-1); 2159 if (i < 0) 2160 i = 0; 2161 move_crsr(scp, i, scp->ypos); 2162 break; 2163 2164 case '`': /* move cursor to column n */ 2165 n = scp->term.param[0]; if (n < 1) n = 1; 2166 move_crsr(scp, n - 1, scp->ypos); 2167 break; 2168 2169 case 'a': /* move cursor n columns to the right */ 2170 n = scp->term.param[0]; if (n < 1) n = 1; 2171 move_crsr(scp, scp->xpos + n, scp->ypos); 2172 break; 2173 2174 case 'd': /* move cursor to row n */ 2175 n = scp->term.param[0]; if (n < 1) n = 1; 2176 move_crsr(scp, scp->xpos, n - 1); 2177 break; 2178 2179 case 'e': /* move cursor n rows down */ 2180 n = scp->term.param[0]; if (n < 1) n = 1; 2181 move_crsr(scp, scp->xpos, scp->ypos + n); 2182 break; 2183 2184 case 'm': /* change attribute */ 2185 if (scp->term.num_param == 0) { 2186 scp->term.attr_mask = NORMAL_ATTR; 2187 scp->term.cur_attr = 2188 scp->term.cur_color = scp->term.std_color; 2189 break; 2190 } 2191 for (i = 0; i < scp->term.num_param; i++) { 2192 switch (n = scp->term.param[i]) { 2193 case 0: /* back to normal */ 2194 scp->term.attr_mask = NORMAL_ATTR; 2195 scp->term.cur_attr = 2196 scp->term.cur_color = scp->term.std_color; 2197 break; 2198 case 1: /* bold */ 2199 scp->term.attr_mask |= BOLD_ATTR; 2200 scp->term.cur_attr = mask2attr(&scp->term); 2201 break; 2202 case 4: /* underline */ 2203 scp->term.attr_mask |= UNDERLINE_ATTR; 2204 scp->term.cur_attr = mask2attr(&scp->term); 2205 break; 2206 case 5: /* blink */ 2207 scp->term.attr_mask |= BLINK_ATTR; 2208 scp->term.cur_attr = mask2attr(&scp->term); 2209 break; 2210 case 7: /* reverse video */ 2211 scp->term.attr_mask |= REVERSE_ATTR; 2212 scp->term.cur_attr = mask2attr(&scp->term); 2213 break; 2214 case 30: case 31: /* set fg color */ 2215 case 32: case 33: case 34: 2216 case 35: case 36: case 37: 2217 scp->term.attr_mask |= FOREGROUND_CHANGED; 2218 scp->term.cur_color = 2219 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2220 scp->term.cur_attr = mask2attr(&scp->term); 2221 break; 2222 case 40: case 41: /* set bg color */ 2223 case 42: case 43: case 44: 2224 case 45: case 46: case 47: 2225 scp->term.attr_mask |= BACKGROUND_CHANGED; 2226 scp->term.cur_color = 2227 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2228 scp->term.cur_attr = mask2attr(&scp->term); 2229 break; 2230 } 2231 } 2232 break; 2233 2234 case 's': /* Save cursor position */ 2235 scp->saved_xpos = scp->xpos; 2236 scp->saved_ypos = scp->ypos; 2237 break; 2238 2239 case 'u': /* Restore saved cursor position */ 2240 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2241 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2242 break; 2243 2244 case 'x': 2245 if (scp->term.num_param == 0) 2246 n = 0; 2247 else 2248 n = scp->term.param[0]; 2249 switch (n) { 2250 case 0: /* reset attributes */ 2251 scp->term.attr_mask = NORMAL_ATTR; 2252 scp->term.cur_attr = 2253 scp->term.cur_color = scp->term.std_color = 2254 current_default->std_color; 2255 scp->term.rev_color = current_default->rev_color; 2256 break; 2257 case 1: /* set ansi background */ 2258 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2259 scp->term.cur_color = scp->term.std_color = 2260 (scp->term.std_color & 0x0F00) | 2261 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2262 scp->term.cur_attr = mask2attr(&scp->term); 2263 break; 2264 case 2: /* set ansi foreground */ 2265 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2266 scp->term.cur_color = scp->term.std_color = 2267 (scp->term.std_color & 0xF000) | 2268 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2269 scp->term.cur_attr = mask2attr(&scp->term); 2270 break; 2271 case 3: /* set ansi attribute directly */ 2272 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2273 scp->term.cur_color = scp->term.std_color = 2274 (scp->term.param[1]&0xFF)<<8; 2275 scp->term.cur_attr = mask2attr(&scp->term); 2276 break; 2277 case 5: /* set ansi reverse video background */ 2278 scp->term.rev_color = 2279 (scp->term.rev_color & 0x0F00) | 2280 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2281 scp->term.cur_attr = mask2attr(&scp->term); 2282 break; 2283 case 6: /* set ansi reverse video foreground */ 2284 scp->term.rev_color = 2285 (scp->term.rev_color & 0xF000) | 2286 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2287 scp->term.cur_attr = mask2attr(&scp->term); 2288 break; 2289 case 7: /* set ansi reverse video directly */ 2290 scp->term.rev_color = 2291 (scp->term.param[1]&0xFF)<<8; 2292 scp->term.cur_attr = mask2attr(&scp->term); 2293 break; 2294 } 2295 break; 2296 2297 case 'z': /* switch to (virtual) console n */ 2298 if (scp->term.num_param == 1) 2299 switch_scr(scp, scp->term.param[0]); 2300 break; 2301 } 2302 } 2303 else if (scp->term.esc == 3) { 2304 if (c >= '0' && c <= '9') { 2305 if (scp->term.num_param < MAX_ESC_PAR) { 2306 if (scp->term.last_param != scp->term.num_param) { 2307 scp->term.last_param = scp->term.num_param; 2308 scp->term.param[scp->term.num_param] = 0; 2309 } 2310 else 2311 scp->term.param[scp->term.num_param] *= 10; 2312 scp->term.param[scp->term.num_param] += c - '0'; 2313 return; 2314 } 2315 } 2316 scp->term.num_param = scp->term.last_param + 1; 2317 switch (c) { 2318 2319 case ';': 2320 if (scp->term.num_param < MAX_ESC_PAR) 2321 return; 2322 break; 2323 2324 case 'A': /* set display border color */ 2325 if ((scp->term.num_param == 1) && crtc_vga) { 2326 scp->border=scp->term.param[0] & 0xff; 2327 if (scp == cur_console) 2328 set_border(scp->border); 2329 } 2330 break; 2331 2332 case 'B': /* set bell pitch and duration */ 2333 if (scp->term.num_param == 2) { 2334 scp->bell_pitch = scp->term.param[0]; 2335 scp->bell_duration = scp->term.param[1]*10; 2336 } 2337 break; 2338 2339 case 'C': /* set cursor type & shape */ 2340 if (scp->term.num_param == 1) { 2341 if (scp->term.param[0] & 0x01) 2342 flags |= BLINK_CURSOR; 2343 else 2344 flags &= ~BLINK_CURSOR; 2345 if ((scp->term.param[0] & 0x02) && crtc_vga) { 2346 flags |= CHAR_CURSOR; 2347 set_destructive_cursor(scp); 2348 } else 2349 flags &= ~CHAR_CURSOR; 2350 } 2351 else if (scp->term.num_param == 2) { 2352 scp->cursor_start = scp->term.param[0] & 0x1F; 2353 scp->cursor_end = scp->term.param[1] & 0x1F; 2354 if (flags & CHAR_CURSOR) 2355 set_destructive_cursor(scp); 2356 } 2357 break; 2358 2359 case 'F': /* set ansi foreground */ 2360 if (scp->term.num_param == 1) { 2361 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2362 scp->term.cur_color = scp->term.std_color = 2363 (scp->term.std_color & 0xF000) 2364 | ((scp->term.param[0] & 0x0F) << 8); 2365 scp->term.cur_attr = mask2attr(&scp->term); 2366 } 2367 break; 2368 2369 case 'G': /* set ansi background */ 2370 if (scp->term.num_param == 1) { 2371 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2372 scp->term.cur_color = scp->term.std_color = 2373 (scp->term.std_color & 0x0F00) 2374 | ((scp->term.param[0] & 0x0F) << 12); 2375 scp->term.cur_attr = mask2attr(&scp->term); 2376 } 2377 break; 2378 2379 case 'H': /* set ansi reverse video foreground */ 2380 if (scp->term.num_param == 1) { 2381 scp->term.rev_color = 2382 (scp->term.rev_color & 0xF000) 2383 | ((scp->term.param[0] & 0x0F) << 8); 2384 scp->term.cur_attr = mask2attr(&scp->term); 2385 } 2386 break; 2387 2388 case 'I': /* set ansi reverse video background */ 2389 if (scp->term.num_param == 1) { 2390 scp->term.rev_color = 2391 (scp->term.rev_color & 0x0F00) 2392 | ((scp->term.param[0] & 0x0F) << 12); 2393 scp->term.cur_attr = mask2attr(&scp->term); 2394 } 2395 break; 2396 } 2397 } 2398 scp->term.esc = 0; 2399} 2400 2401static void 2402ansi_put(scr_stat *scp, u_char *buf, int len) 2403{ 2404 u_char *ptr = buf; 2405 2406 /* make screensaver happy */ 2407 if (scp == cur_console) { 2408 scrn_time_stamp = time.tv_sec; 2409 if (scrn_blanked) { 2410 (*current_saver)(FALSE); 2411 mark_all(scp); 2412 } 2413 } 2414 write_in_progress++; 2415outloop: 2416 if (scp->term.esc) { 2417 scan_esc(scp, *ptr++); 2418 len--; 2419 } 2420 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2421 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2422 u_short cur_attr = scp->term.cur_attr; 2423 u_short *cursor_pos = scp->cursor_pos; 2424 do { 2425 /* 2426 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2427 * pointers in the following to volatile should have no effect, 2428 * but in fact speeds up this inner loop from 26 to 18 cycles 2429 * (+ cache misses) on i486's. 2430 */ 2431#define UCVP(ucp) ((u_char volatile *)(ucp)) 2432 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2433 ptr++; 2434 cnt--; 2435 } while (cnt && PRINTABLE(*ptr)); 2436 len -= (cursor_pos - scp->cursor_pos); 2437 scp->xpos += (cursor_pos - scp->cursor_pos); 2438 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2439 mark_for_update(scp, cursor_pos - scp->scr_buf); 2440 scp->cursor_pos = cursor_pos; 2441 if (scp->xpos >= scp->xsize) { 2442 scp->xpos = 0; 2443 scp->ypos++; 2444 } 2445 } 2446 else { 2447 switch(*ptr) { 2448 case 0x07: 2449 do_bell(scp, scp->bell_pitch, scp->bell_duration); 2450 break; 2451 2452 case 0x08: /* non-destructive backspace */ 2453 if (scp->cursor_pos > scp->scr_buf) { 2454 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2455 scp->cursor_pos--; 2456 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2457 if (scp->xpos > 0) 2458 scp->xpos--; 2459 else { 2460 scp->xpos += scp->xsize - 1; 2461 scp->ypos--; 2462 } 2463 } 2464 break; 2465 2466 case 0x09: /* non-destructive tab */ 2467 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2468 scp->cursor_pos += (8 - scp->xpos % 8u); 2469 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2470 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 2471 scp->xpos = 0; 2472 scp->ypos++; 2473 } 2474 break; 2475 2476 case 0x0a: /* newline, same pos */ 2477 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2478 scp->cursor_pos += scp->xsize; 2479 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2480 scp->ypos++; 2481 break; 2482 2483 case 0x0c: /* form feed, clears screen */ 2484 clear_screen(scp); 2485 break; 2486 2487 case 0x0d: /* return, return to pos 0 */ 2488 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2489 scp->cursor_pos -= scp->xpos; 2490 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2491 scp->xpos = 0; 2492 break; 2493 2494 case 0x1b: /* start escape sequence */ 2495 scp->term.esc = 1; 2496 scp->term.num_param = 0; 2497 break; 2498 } 2499 ptr++; len--; 2500 } 2501 /* do we have to scroll ?? */ 2502 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 2503 remove_cutmarking(scp); 2504 if (scp->history) { 2505 bcopy(scp->scr_buf, scp->history_head, 2506 scp->xsize * sizeof(u_short)); 2507 scp->history_head += scp->xsize; 2508 if (scp->history_head + scp->xsize > 2509 scp->history + scp->history_size) 2510 scp->history_head = scp->history; 2511 } 2512 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 2513 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2514 fillw(scp->term.cur_color | scr_map[0x20], 2515 scp->scr_buf + scp->xsize * (scp->ysize - 1), 2516 scp->xsize); 2517 scp->cursor_pos -= scp->xsize; 2518 scp->ypos--; 2519 mark_all(scp); 2520 } 2521 if (len) 2522 goto outloop; 2523 write_in_progress--; 2524 if (delayed_next_scr) 2525 switch_scr(scp, delayed_next_scr - 1); 2526} 2527 2528static void 2529scinit(void) 2530{ 2531 u_int hw_cursor; 2532 u_int i; 2533 2534 if (init_done != COLD) 2535 return; 2536 init_done = WARM; 2537 2538 /* 2539 * Ensure a zero start address. This is mainly to recover after 2540 * switching from pcvt using userconfig(). The registers are w/o 2541 * for old hardware so it's too hard to relocate the active screen 2542 * memory. 2543 */ 2544 outb(crtc_addr, 12); 2545 outb(crtc_addr + 1, 0); 2546 outb(crtc_addr, 13); 2547 outb(crtc_addr + 1, 0); 2548 2549 /* extract cursor location */ 2550 outb(crtc_addr, 14); 2551 hw_cursor = inb(crtc_addr + 1) << 8; 2552 outb(crtc_addr, 15); 2553 hw_cursor |= inb(crtc_addr + 1); 2554 2555 /* 2556 * Validate cursor location. It may be off the screen. Then we must 2557 * not use it for the initial buffer offset. 2558 */ 2559 if (hw_cursor >= ROW * COL) 2560 hw_cursor = (ROW - 1) * COL; 2561 2562 /* move hardware cursor out of the way */ 2563 outb(crtc_addr, 14); 2564 outb(crtc_addr + 1, 0xff); 2565 outb(crtc_addr, 15); 2566 outb(crtc_addr + 1, 0xff); 2567 2568 /* set up the first console */ 2569 current_default = &user_default; 2570 console[0] = &main_console; 2571 init_scp(console[0]); 2572 cur_console = console[0]; 2573 2574 /* discard the video mode table if we are not familiar with it... */ 2575 if (video_mode_ptr) { 2576 if (comp_vgaregs(vgaregs, video_mode_ptr + 64*console[0]->mode)) 2577 video_mode_ptr = NULL; 2578 } 2579 2580 /* copy screen to temporary buffer */ 2581 sc_bcopy(Crtat, sc_buffer, 2582 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 2583 2584 console[0]->scr_buf = console[0]->mouse_pos = sc_buffer; 2585 console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; 2586 console[0]->xpos = hw_cursor % COL; 2587 console[0]->ypos = hw_cursor / COL; 2588 for (i=1; i<MAXCONS; i++) 2589 console[i] = NULL; 2590 kernel_console.esc = 0; 2591 kernel_console.attr_mask = NORMAL_ATTR; 2592 kernel_console.cur_attr = 2593 kernel_console.cur_color = kernel_console.std_color = 2594 kernel_default.std_color; 2595 kernel_console.rev_color = kernel_default.rev_color; 2596 2597 /* initialize mapscrn arrays to a one to one map */ 2598 for (i=0; i<sizeof(scr_map); i++) { 2599 scr_map[i] = scr_rmap[i] = i; 2600 } 2601 2602 /* Save font and palette if VGA */ 2603 if (crtc_vga) { 2604 copy_font(SAVE, FONT_16, font_16); 2605 fonts_loaded = FONT_16; 2606 save_palette(); 2607 } 2608 2609#ifdef SC_SPLASH_SCREEN 2610 /* 2611 * Now put up a graphics image, and maybe cycle a 2612 * couble of palette entries for simple animation. 2613 */ 2614 toggle_splash_screen(cur_console); 2615#endif 2616} 2617 2618static scr_stat 2619*alloc_scp() 2620{ 2621 scr_stat *scp; 2622 2623 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 2624 init_scp(scp); 2625 scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos = 2626 (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 2627 M_DEVBUF, M_WAITOK); 2628 scp->mouse_pos = scp->mouse_oldpos = 2629 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 2630 scp->mouse_xpos/8); 2631 scp->history_head = scp->history_pos = scp->history = 2632 (u_short *)malloc(scp->history_size*sizeof(u_short), 2633 M_DEVBUF, M_WAITOK); 2634 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 2635/* SOS 2636 if (crtc_vga && video_mode_ptr) 2637 set_mode(scp); 2638*/ 2639 clear_screen(scp); 2640 return scp; 2641} 2642 2643static void 2644init_scp(scr_stat *scp) 2645{ 2646 if (crtc_vga) 2647 if (crtc_addr == MONO_BASE) 2648 scp->mode = M_VGA_M80x25; 2649 else 2650 scp->mode = M_VGA_C80x25; 2651 else 2652 if (crtc_addr == MONO_BASE) 2653 scp->mode = M_B80x25; 2654 else 2655 scp->mode = M_C80x25; 2656 2657 scp->font_size = 16; 2658 scp->xsize = COL; 2659 scp->ysize = ROW; 2660 scp->xpos = scp->ypos = 0; 2661 scp->saved_xpos = scp->saved_ypos = -1; 2662 scp->start = scp->xsize * scp->ysize; 2663 scp->end = 0; 2664 scp->term.esc = 0; 2665 scp->term.attr_mask = NORMAL_ATTR; 2666 scp->term.cur_attr = 2667 scp->term.cur_color = scp->term.std_color = 2668 current_default->std_color; 2669 scp->term.rev_color = current_default->rev_color; 2670 scp->border = BG_BLACK; 2671 scp->cursor_start = *(char *)pa_to_va(0x461); 2672 scp->cursor_end = *(char *)pa_to_va(0x460); 2673 scp->mouse_xpos = scp->xsize*8/2; 2674 scp->mouse_ypos = scp->ysize*scp->font_size/2; 2675 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 2676 scp->mouse_signal = 0; 2677 scp->mouse_pid = 0; 2678 scp->mouse_proc = NULL; 2679 scp->bell_pitch = BELL_PITCH; 2680 scp->bell_duration = BELL_DURATION; 2681 scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 2682 scp->status |= CURSOR_ENABLED; 2683 scp->pid = 0; 2684 scp->proc = NULL; 2685 scp->smode.mode = VT_AUTO; 2686 scp->history_head = scp->history_pos = scp->history = NULL; 2687 scp->history_size = HISTORY_SIZE; 2688} 2689 2690static u_char 2691*get_fstr(u_int c, u_int *len) 2692{ 2693 u_int i; 2694 2695 if (!(c & FKEY)) 2696 return(NULL); 2697 i = (c & 0xFF) - F_FN; 2698 if (i > n_fkey_tab) 2699 return(NULL); 2700 *len = fkey_tab[i].len; 2701 return(fkey_tab[i].str); 2702} 2703 2704static void 2705history_to_screen(scr_stat *scp) 2706{ 2707 int i; 2708 2709 for (i=0; i<scp->ysize; i++) 2710 bcopy(scp->history + (((scp->history_pos - scp->history) + 2711 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 2712 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 2713 scp->xsize * sizeof(u_short)); 2714 mark_all(scp); 2715} 2716 2717static int 2718history_up_line(scr_stat *scp) 2719{ 2720 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 2721 scp->history_head) { 2722 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 2723 history_to_screen(scp); 2724 return 0; 2725 } 2726 else 2727 return -1; 2728} 2729 2730static int 2731history_down_line(scr_stat *scp) 2732{ 2733 if (scp->history_pos != scp->history_head) { 2734 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 2735 history_to_screen(scp); 2736 return 0; 2737 } 2738 else 2739 return -1; 2740} 2741 2742/* 2743 * scgetc(flags) - get character from keyboard. 2744 * If flags & SCGETC_CN, then avoid harmful side effects. 2745 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 2746 * return NOKEY if there is nothing there. 2747 */ 2748static u_int 2749scgetc(u_int flags) 2750{ 2751 struct key_t *key; 2752 u_char scancode, keycode; 2753 u_int state, action; 2754 int c; 2755 static u_char esc_flag = 0, compose = 0; 2756 static u_int chr = 0; 2757 2758next_code: 2759 /* first see if there is something in the keyboard port */ 2760 if (flags & SCGETC_NONBLOCK) { 2761 c = read_kbd_data_no_wait(sc_kbdc); 2762 if (c == -1) 2763 return(NOKEY); 2764 } else { 2765 do { 2766 c = read_kbd_data(sc_kbdc); 2767 } while(c == -1); 2768 } 2769 scancode = (u_char)c; 2770 2771 /* do the /dev/random device a favour */ 2772 if (!(flags & SCGETC_CN)) 2773 add_keyboard_randomness(scancode); 2774 2775 if (cur_console->status & KBD_RAW_MODE) 2776 return scancode; 2777 2778 keycode = scancode & 0x7F; 2779 switch (esc_flag) { 2780 case 0x00: /* normal scancode */ 2781 switch(scancode) { 2782 case 0xB8: /* left alt (compose key) */ 2783 if (compose) { 2784 compose = 0; 2785 if (chr > 255) { 2786 do_bell(cur_console, 2787 BELL_PITCH, BELL_DURATION); 2788 chr = 0; 2789 } 2790 } 2791 break; 2792 case 0x38: 2793 if (!compose) { 2794 compose = 1; 2795 chr = 0; 2796 } 2797 break; 2798 case 0xE0: 2799 case 0xE1: 2800 esc_flag = scancode; 2801 goto next_code; 2802 } 2803 break; 2804 case 0xE0: /* 0xE0 prefix */ 2805 esc_flag = 0; 2806 switch (keycode) { 2807 case 0x1C: /* right enter key */ 2808 keycode = 0x59; 2809 break; 2810 case 0x1D: /* right ctrl key */ 2811 keycode = 0x5A; 2812 break; 2813 case 0x35: /* keypad divide key */ 2814 keycode = 0x5B; 2815 break; 2816 case 0x37: /* print scrn key */ 2817 keycode = 0x5C; 2818 break; 2819 case 0x38: /* right alt key (alt gr) */ 2820 keycode = 0x5D; 2821 break; 2822 case 0x47: /* grey home key */ 2823 keycode = 0x5E; 2824 break; 2825 case 0x48: /* grey up arrow key */ 2826 keycode = 0x5F; 2827 break; 2828 case 0x49: /* grey page up key */ 2829 keycode = 0x60; 2830 break; 2831 case 0x4B: /* grey left arrow key */ 2832 keycode = 0x61; 2833 break; 2834 case 0x4D: /* grey right arrow key */ 2835 keycode = 0x62; 2836 break; 2837 case 0x4F: /* grey end key */ 2838 keycode = 0x63; 2839 break; 2840 case 0x50: /* grey down arrow key */ 2841 keycode = 0x64; 2842 break; 2843 case 0x51: /* grey page down key */ 2844 keycode = 0x65; 2845 break; 2846 case 0x52: /* grey insert key */ 2847 keycode = 0x66; 2848 break; 2849 case 0x53: /* grey delete key */ 2850 keycode = 0x67; 2851 break; 2852 2853 /* the following 3 are only used on the MS "Natural" keyboard */ 2854 case 0x5b: /* left Window key */ 2855 keycode = 0x69; 2856 break; 2857 case 0x5c: /* right Window key */ 2858 keycode = 0x6a; 2859 break; 2860 case 0x5d: /* menu key */ 2861 keycode = 0x6b; 2862 break; 2863 default: /* ignore everything else */ 2864 goto next_code; 2865 } 2866 break; 2867 case 0xE1: /* 0xE1 prefix */ 2868 esc_flag = 0; 2869 if (keycode == 0x1D) 2870 esc_flag = 0x1D; 2871 goto next_code; 2872 /* NOT REACHED */ 2873 case 0x1D: /* pause / break */ 2874 esc_flag = 0; 2875 if (keycode != 0x45) 2876 goto next_code; 2877 keycode = 0x68; 2878 break; 2879 } 2880 2881 /* if scroll-lock pressed allow history browsing */ 2882 if (cur_console->history && cur_console->status & SLKED) { 2883 int i; 2884 2885 cur_console->status &= ~CURSOR_ENABLED; 2886 if (!(cur_console->status & BUFFER_SAVED)) { 2887 cur_console->status |= BUFFER_SAVED; 2888 cur_console->history_save = cur_console->history_head; 2889 2890 /* copy screen into top of history buffer */ 2891 for (i=0; i<cur_console->ysize; i++) { 2892 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 2893 cur_console->history_head, 2894 cur_console->xsize * sizeof(u_short)); 2895 cur_console->history_head += cur_console->xsize; 2896 if (cur_console->history_head + cur_console->xsize > 2897 cur_console->history + cur_console->history_size) 2898 cur_console->history_head=cur_console->history; 2899 } 2900 cur_console->history_pos = cur_console->history_head; 2901 history_to_screen(cur_console); 2902 } 2903 switch (scancode) { 2904 case 0x47: /* home key */ 2905 cur_console->history_pos = cur_console->history_head; 2906 history_to_screen(cur_console); 2907 goto next_code; 2908 2909 case 0x4F: /* end key */ 2910 cur_console->history_pos = 2911 WRAPHIST(cur_console, cur_console->history_head, 2912 cur_console->xsize*cur_console->ysize); 2913 history_to_screen(cur_console); 2914 goto next_code; 2915 2916 case 0x48: /* up arrow key */ 2917 if (history_up_line(cur_console)) 2918 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2919 goto next_code; 2920 2921 case 0x50: /* down arrow key */ 2922 if (history_down_line(cur_console)) 2923 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2924 goto next_code; 2925 2926 case 0x49: /* page up key */ 2927 for (i=0; i<cur_console->ysize; i++) 2928 if (history_up_line(cur_console)) { 2929 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2930 break; 2931 } 2932 goto next_code; 2933 2934 case 0x51: /* page down key */ 2935 for (i=0; i<cur_console->ysize; i++) 2936 if (history_down_line(cur_console)) { 2937 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2938 break; 2939 } 2940 goto next_code; 2941 } 2942 } 2943 2944 if (compose) { 2945 switch (scancode) { 2946 /* key pressed process it */ 2947 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 2948 chr = (scancode - 0x40) + chr*10; 2949 goto next_code; 2950 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 2951 chr = (scancode - 0x47) + chr*10; 2952 goto next_code; 2953 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 2954 chr = (scancode - 0x4E) + chr*10; 2955 goto next_code; 2956 case 0x52: /* keypad 0 */ 2957 chr *= 10; 2958 goto next_code; 2959 2960 /* key release, no interest here */ 2961 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 2962 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 2963 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 2964 case 0xD2: /* keypad 0 */ 2965 goto next_code; 2966 2967 case 0x38: /* left alt key */ 2968 break; 2969 default: 2970 if (chr) { 2971 compose = chr = 0; 2972 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2973 goto next_code; 2974 } 2975 break; 2976 } 2977 } 2978 2979 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2980 if ((!agrs && (cur_console->status & ALKED)) 2981 || (agrs && !(cur_console->status & ALKED))) 2982 keycode += ALTGR_OFFSET; 2983 key = &key_map.key[keycode]; 2984 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2985 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2986 state ^= 1; 2987 2988 /* Check for make/break */ 2989 action = key->map[state]; 2990 if (scancode & 0x80) { /* key released */ 2991 if (key->spcl & 0x80) { 2992 switch (action) { 2993 case LSH: 2994 shfts &= ~1; 2995 break; 2996 case RSH: 2997 shfts &= ~2; 2998 break; 2999 case LCTR: 3000 ctls &= ~1; 3001 break; 3002 case RCTR: 3003 ctls &= ~2; 3004 break; 3005 case LALT: 3006 alts &= ~1; 3007 break; 3008 case RALT: 3009 alts &= ~2; 3010 break; 3011 case NLK: 3012 nlkcnt = 0; 3013 break; 3014 case CLK: 3015 clkcnt = 0; 3016 break; 3017 case SLK: 3018 slkcnt = 0; 3019 break; 3020 case ASH: 3021 agrs = 0; 3022 break; 3023 case ALK: 3024 alkcnt = 0; 3025 break; 3026 case META: 3027 metas = 0; 3028 break; 3029 } 3030 } 3031 if (chr && !compose) { 3032 action = chr; 3033 chr = 0; 3034 return(action); 3035 } 3036 } else { 3037 /* key pressed */ 3038 if (key->spcl & (0x80>>state)) { 3039 switch (action) { 3040 /* LOCKING KEYS */ 3041 case NLK: 3042#ifdef SC_SPLASH_SCREEN 3043 toggle_splash_screen(cur_console); /* SOS XXX */ 3044#endif 3045 if (!nlkcnt) { 3046 nlkcnt++; 3047 if (cur_console->status & NLKED) 3048 cur_console->status &= ~NLKED; 3049 else 3050 cur_console->status |= NLKED; 3051 update_leds(cur_console->status); 3052 } 3053 break; 3054 case CLK: 3055 if (!clkcnt) { 3056 clkcnt++; 3057 if (cur_console->status & CLKED) 3058 cur_console->status &= ~CLKED; 3059 else 3060 cur_console->status |= CLKED; 3061 update_leds(cur_console->status); 3062 } 3063 break; 3064 case SLK: 3065 if (!slkcnt) { 3066 slkcnt++; 3067 if (cur_console->status & SLKED) { 3068 cur_console->status &= ~SLKED; 3069 if (cur_console->status & BUFFER_SAVED){ 3070 int i; 3071 u_short *ptr = cur_console->history_save; 3072 3073 for (i=0; i<cur_console->ysize; i++) { 3074 bcopy(ptr, 3075 cur_console->scr_buf + 3076 (cur_console->xsize*i), 3077 cur_console->xsize * sizeof(u_short)); 3078 ptr += cur_console->xsize; 3079 if (ptr + cur_console->xsize > 3080 cur_console->history + 3081 cur_console->history_size) 3082 ptr = cur_console->history; 3083 } 3084 cur_console->status &= ~BUFFER_SAVED; 3085 cur_console->history_head=cur_console->history_save; 3086 cur_console->status |= CURSOR_ENABLED; 3087 mark_all(cur_console); 3088 } 3089 scstart(VIRTUAL_TTY(get_scr_num())); 3090 } 3091 else 3092 cur_console->status |= SLKED; 3093 update_leds(cur_console->status); 3094 } 3095 break; 3096 case ALK: 3097 if (!alkcnt) { 3098 alkcnt++; 3099 if (cur_console->status & ALKED) 3100 cur_console->status &= ~ALKED; 3101 else 3102 cur_console->status |= ALKED; 3103 update_leds(cur_console->status); 3104 } 3105 break; 3106 3107 /* NON-LOCKING KEYS */ 3108 case NOP: 3109 break; 3110 case SPSC: 3111#ifdef SC_SPLASH_SCREEN 3112 toggle_splash_screen(cur_console); 3113#endif 3114 break; 3115 case RBT: 3116 shutdown_nice(); 3117 break; 3118 case SUSP: 3119#if NAPM > 0 3120 apm_suspend(); 3121#endif 3122 break; 3123 3124 case DBG: 3125#ifdef DDB /* try to switch to console 0 */ 3126 if (cur_console->smode.mode == VT_AUTO && 3127 console[0]->smode.mode == VT_AUTO) 3128 switch_scr(cur_console, 0); 3129 Debugger("manual escape to debugger"); 3130#else 3131 printf("No debugger in kernel\n"); 3132#endif 3133 break; 3134 case LSH: 3135 shfts |= 1; 3136 break; 3137 case RSH: 3138 shfts |= 2; 3139 break; 3140 case LCTR: 3141 ctls |= 1; 3142 break; 3143 case RCTR: 3144 ctls |= 2; 3145 break; 3146 case LALT: 3147 alts |= 1; 3148 break; 3149 case RALT: 3150 alts |= 2; 3151 break; 3152 case ASH: 3153 agrs = 1; 3154 break; 3155 case META: 3156 metas = 1; 3157 break; 3158 case NEXT: 3159 { 3160 int next, this = get_scr_num(); 3161 for (next = this+1; next != this; next = (next+1)%MAXCONS) { 3162 struct tty *tp = VIRTUAL_TTY(next); 3163 if (tp->t_state & TS_ISOPEN) { 3164 switch_scr(cur_console, next); 3165 break; 3166 } 3167 } 3168 } 3169 break; 3170 case BTAB: 3171 return(BKEY); 3172 default: 3173 if (action >= F_SCR && action <= L_SCR) { 3174 switch_scr(cur_console, action - F_SCR); 3175 break; 3176 } 3177 if (action >= F_FN && action <= L_FN) 3178 action |= FKEY; 3179 return(action); 3180 } 3181 } 3182 else { 3183 if (metas) 3184 action |= MKEY; 3185 return(action); 3186 } 3187 } 3188 goto next_code; 3189} 3190 3191int 3192scmmap(dev_t dev, int offset, int nprot) 3193{ 3194 if (offset > 0x20000 - PAGE_SIZE) 3195 return -1; 3196 return i386_btop((VIDEOMEM + offset)); 3197} 3198 3199/* 3200 * Calculate hardware attributes word using logical attributes mask and 3201 * hardware colors 3202 */ 3203 3204static int 3205mask2attr(struct term_stat *term) 3206{ 3207 int attr, mask = term->attr_mask; 3208 3209 if (mask & REVERSE_ATTR) { 3210 attr = ((mask & FOREGROUND_CHANGED) ? 3211 ((term->cur_color & 0xF000) >> 4) : 3212 (term->rev_color & 0x0F00)) | 3213 ((mask & BACKGROUND_CHANGED) ? 3214 ((term->cur_color & 0x0F00) << 4) : 3215 (term->rev_color & 0xF000)); 3216 } else 3217 attr = term->cur_color; 3218 3219 /* XXX: underline mapping for Hercules adapter can be better */ 3220 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3221 attr ^= 0x0800; 3222 if (mask & BLINK_ATTR) 3223 attr ^= 0x8000; 3224 3225 return attr; 3226} 3227 3228static void 3229set_keyboard(int command, int data) 3230{ 3231 int s; 3232 int c; 3233 3234 if (sc_kbdc == NULL) 3235 return; 3236 3237 /* prevent the timeout routine from polling the keyboard */ 3238 if (!kbdc_lock(sc_kbdc, TRUE)) 3239 return; 3240 3241 /* disable the keyboard and mouse interrupt */ 3242 s = spltty(); 3243#if 0 3244 c = get_controller_command_byte(sc_kbdc); 3245 if ((c == -1) 3246 || !set_controller_command_byte(sc_kbdc, 3247 kbdc_get_device_mask(sc_kbdc), 3248 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 3249 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 3250 /* CONTROLLER ERROR */ 3251 kbdc_lock(sc_kbdc, FALSE); 3252 splx(s); 3253 return; 3254 } 3255 /* 3256 * Now that the keyboard controller is told not to generate 3257 * the keyboard and mouse interrupts, call `splx()' to allow 3258 * the other tty interrupts. The clock interrupt may also occur, 3259 * but the timeout routine (`scrn_timer()') will be blocked 3260 * by the lock flag set via `kbdc_lock()' 3261 */ 3262 splx(s); 3263#endif 3264 3265 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) 3266 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); 3267 3268#if 0 3269 /* restore the interrupts */ 3270 if (!set_controller_command_byte(sc_kbdc, 3271 kbdc_get_device_mask(sc_kbdc), 3272 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 3273 /* CONTROLLER ERROR */ 3274 } 3275#else 3276 splx(s); 3277#endif 3278 kbdc_lock(sc_kbdc, FALSE); 3279} 3280 3281static void 3282update_leds(int which) 3283{ 3284 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 3285 3286 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 3287 if (key_map.n_keys > ALTGR_OFFSET) { 3288 if (which & ALKED) 3289 which |= CLKED; 3290 else 3291 which &= ~CLKED; 3292 } 3293 3294 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); 3295} 3296 3297void 3298set_mode(scr_stat *scp) 3299{ 3300 char *modetable; 3301 char special_modetable[64]; 3302 3303 if (scp != cur_console) 3304 return; 3305 3306 /* setup video hardware for the given mode */ 3307 switch (scp->mode) { 3308 case M_VGA_M80x60: 3309 bcopy(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 3310 goto special_80x60; 3311 3312 case M_VGA_C80x60: 3313 bcopy(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 3314special_80x60: 3315 special_modetable[2] = 0x08; 3316 special_modetable[19] = 0x47; 3317 goto special_480l; 3318 3319 case M_VGA_M80x30: 3320 bcopy(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 3321 goto special_80x30; 3322 3323 case M_VGA_C80x30: 3324 bcopy(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 3325special_80x30: 3326 special_modetable[19] = 0x4f; 3327special_480l: 3328 special_modetable[9] |= 0xc0; 3329 special_modetable[16] = 0x08; 3330 special_modetable[17] = 0x3e; 3331 special_modetable[26] = 0xea; 3332 special_modetable[28] = 0xdf; 3333 special_modetable[31] = 0xe7; 3334 special_modetable[32] = 0x04; 3335 modetable = special_modetable; 3336 goto setup_mode; 3337 3338 case M_ENH_B80x43: 3339 bcopy(video_mode_ptr+(64*M_ENH_B80x25), &special_modetable, 64); 3340 goto special_80x43; 3341 3342 case M_ENH_C80x43: 3343 bcopy(video_mode_ptr+(64*M_ENH_C80x25), &special_modetable, 64); 3344special_80x43: 3345 special_modetable[28] = 87; 3346 goto special_80x50; 3347 3348 case M_VGA_M80x50: 3349 bcopy(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 3350 goto special_80x50; 3351 3352 case M_VGA_C80x50: 3353 bcopy(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 3354special_80x50: 3355 special_modetable[2] = 8; 3356 special_modetable[19] = 7; 3357 modetable = special_modetable; 3358 goto setup_mode; 3359 3360 case M_VGA_C40x25: case M_VGA_C80x25: 3361 case M_VGA_M80x25: 3362 case M_B40x25: case M_C40x25: 3363 case M_B80x25: case M_C80x25: 3364 case M_ENH_B40x25: case M_ENH_C40x25: 3365 case M_ENH_B80x25: case M_ENH_C80x25: 3366 case M_EGAMONO80x25: 3367 3368 modetable = video_mode_ptr + (scp->mode * 64); 3369setup_mode: 3370 set_vgaregs(modetable); 3371 scp->font_size = *(modetable + 2); 3372 3373 /* set font type (size) */ 3374 if (scp->font_size < 14) { 3375 if (fonts_loaded & FONT_8) 3376 copy_font(LOAD, FONT_8, font_8); 3377 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 3378 } else if (scp->font_size >= 16) { 3379 if (fonts_loaded & FONT_16) 3380 copy_font(LOAD, FONT_16, font_16); 3381 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 3382 } else { 3383 if (fonts_loaded & FONT_14) 3384 copy_font(LOAD, FONT_14, font_14); 3385 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 3386 } 3387 if (flags & CHAR_CURSOR) 3388 set_destructive_cursor(scp); 3389 mark_all(scp); 3390 break; 3391 3392 case M_BG320: case M_CG320: case M_BG640: 3393 case M_CG320_D: case M_CG640_E: 3394 case M_CG640x350: case M_ENH_CG640: 3395 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 3396 3397 set_vgaregs(video_mode_ptr + (scp->mode * 64)); 3398 scp->font_size = FONT_NONE; 3399 break; 3400 3401 default: 3402 /* call user defined function XXX */ 3403 break; 3404 } 3405 3406 /* set border color for this (virtual) console */ 3407 set_border(scp->border); 3408 return; 3409} 3410 3411void 3412set_border(u_char color) 3413{ 3414 inb(crtc_addr+6); /* reset flip-flop */ 3415 outb(ATC, 0x11); outb(ATC, color); 3416 inb(crtc_addr+6); /* reset flip-flop */ 3417 outb(ATC, 0x20); /* enable Palette */ 3418} 3419 3420static void 3421set_vgaregs(char *modetable) 3422{ 3423 int i, s = splhigh(); 3424 3425 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 3426 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 3427 for (i=0; i<4; i++) { /* program sequencer */ 3428 outb(TSIDX, i+1); 3429 outb(TSREG, modetable[i+5]); 3430 } 3431 outb(MISC, modetable[9]); /* set dot-clock */ 3432 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 3433 outb(crtc_addr, 0x11); 3434 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 3435 for (i=0; i<25; i++) { /* program crtc */ 3436 outb(crtc_addr, i); 3437 if (i == 14 || i == 15) /* no hardware cursor */ 3438 outb(crtc_addr+1, 0xff); 3439 else 3440 outb(crtc_addr+1, modetable[i+10]); 3441 } 3442 inb(crtc_addr+6); /* reset flip-flop */ 3443 for (i=0; i<20; i++) { /* program attribute ctrl */ 3444 outb(ATC, i); 3445 outb(ATC, modetable[i+35]); 3446 } 3447 for (i=0; i<9; i++) { /* program graph data ctrl */ 3448 outb(GDCIDX, i); 3449 outb(GDCREG, modetable[i+55]); 3450 } 3451 inb(crtc_addr+6); /* reset flip-flop */ 3452 outb(ATC, 0x20); /* enable palette */ 3453 splx(s); 3454} 3455 3456static void 3457read_vgaregs(char *buf) 3458{ 3459 int i, j; 3460 int s; 3461 3462 bzero(buf, 64); 3463 3464 s = splhigh(); 3465 3466 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 3467 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 3468 for (i=0, j=5; i<4; i++) { 3469 outb(TSIDX, i+1); 3470 buf[j++] = inb(TSREG); 3471 } 3472 buf[9] = inb(MISC + 10); /* dot-clock */ 3473 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 3474 3475 for (i=0, j=10; i<25; i++) { /* crtc */ 3476 outb(crtc_addr, i); 3477 buf[j++] = inb(crtc_addr+1); 3478 } 3479 for (i=0, j=35; i<20; i++) { /* attribute ctrl */ 3480 inb(crtc_addr+6); /* reset flip-flop */ 3481 outb(ATC, i); 3482 buf[j++] = inb(ATC + 1); 3483 } 3484 for (i=0, j=55; i<9; i++) { /* graph data ctrl */ 3485 outb(GDCIDX, i); 3486 buf[j++] = inb(GDCREG); 3487 } 3488 inb(crtc_addr+6); /* reset flip-flop */ 3489 outb(ATC, 0x20); /* enable palette */ 3490 3491 buf[0] = *(char *)pa_to_va(0x44a); /* COLS */ 3492 buf[1] = *(char *)pa_to_va(0x484); /* ROWS */ 3493 buf[2] = *(char *)pa_to_va(0x485); /* POINTS */ 3494 buf[3] = *(char *)pa_to_va(0x44c); 3495 buf[4] = *(char *)pa_to_va(0x44d); 3496 3497 splx(s); 3498} 3499 3500static int 3501comp_vgaregs(u_char *buf1, u_char *buf2) 3502{ 3503 int i; 3504 3505 for(i = 0; i < 20; ++i) { 3506 if (*buf1++ != *buf2++) 3507 return 1; 3508 } 3509 buf1 += 2; /* skip the cursor shape */ 3510 buf2 += 2; 3511 for(i = 22; i < 24; ++i) { 3512 if (*buf1++ != *buf2++) 3513 return 1; 3514 } 3515 buf1 += 2; /* skip the cursor position */ 3516 buf2 += 2; 3517 for(i = 26; i < 64; ++i) { 3518 if (*buf1++ != *buf2++) 3519 return 1; 3520 } 3521 return 0; 3522} 3523 3524static void 3525dump_vgaregs(u_char *buf) 3526{ 3527 int i; 3528 3529 for(i = 0; i < 64;) { 3530 printf("%02x ", buf[i]); 3531 if ((++i % 16) == 0) 3532 printf("\n"); 3533 } 3534} 3535 3536static void 3537set_font_mode() 3538{ 3539 int s = splhigh(); 3540 3541 /* setup vga for loading fonts (graphics plane mode) */ 3542 inb(crtc_addr+6); /* reset flip-flop */ 3543 outb(ATC, 0x10); outb(ATC, 0x01); 3544 inb(crtc_addr+6); /* reset flip-flop */ 3545 outb(ATC, 0x20); /* enable palette */ 3546 3547#if SLOW_VGA 3548 outb(TSIDX, 0x02); outb(TSREG, 0x04); 3549 outb(TSIDX, 0x04); outb(TSREG, 0x06); 3550 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 3551 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 3552 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); 3553#else 3554 outw(TSIDX, 0x0402); 3555 outw(TSIDX, 0x0604); 3556 outw(GDCIDX, 0x0204); 3557 outw(GDCIDX, 0x0005); 3558 outw(GDCIDX, 0x0506); /* addr = a0000, 64kb */ 3559#endif 3560 splx(s); 3561} 3562 3563static void 3564set_normal_mode() 3565{ 3566 char *modetable; 3567 int s = splhigh(); 3568 3569 switch (cur_console->mode) { 3570 case M_VGA_M80x60: 3571 case M_VGA_M80x50: 3572 case M_VGA_M80x30: 3573 modetable = video_mode_ptr + (64*M_VGA_M80x25); 3574 break; 3575 3576 case M_VGA_C80x60: 3577 case M_VGA_C80x50: 3578 case M_VGA_C80x30: 3579 modetable = video_mode_ptr + (64*M_VGA_C80x25); 3580 break; 3581 3582 case M_ENH_B80x43: 3583 modetable = video_mode_ptr + (64*M_ENH_B80x25); 3584 break; 3585 3586 case M_ENH_C80x43: 3587 modetable = video_mode_ptr + (64*M_ENH_C80x25); 3588 break; 3589 3590 case M_VGA_C40x25: case M_VGA_C80x25: 3591 case M_VGA_M80x25: 3592 case M_B40x25: case M_C40x25: 3593 case M_B80x25: case M_C80x25: 3594 case M_ENH_B40x25: case M_ENH_C40x25: 3595 case M_ENH_B80x25: case M_ENH_C80x25: 3596 case M_EGAMONO80x25: 3597 3598 case M_BG320: case M_CG320: case M_BG640: 3599 case M_CG320_D: case M_CG640_E: 3600 case M_CG640x350: case M_ENH_CG640: 3601 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 3602 modetable = video_mode_ptr + (cur_console->mode * 64); 3603 break; 3604 3605 default: 3606 modetable = video_mode_ptr + (64*M_VGA_C80x25); 3607 } 3608 3609 if (video_mode_ptr == NULL) 3610 modetable = vgaregs; 3611 3612 /* setup vga for normal operation mode again */ 3613 inb(crtc_addr+6); /* reset flip-flop */ 3614 outb(ATC, 0x10); outb(ATC, modetable[0x10+35]); 3615 inb(crtc_addr+6); /* reset flip-flop */ 3616 outb(ATC, 0x20); /* enable palette */ 3617#if SLOW_VGA 3618 outb(TSIDX, 0x02); outb(TSREG, modetable[0x02+4]); 3619 outb(TSIDX, 0x04); outb(TSREG, modetable[0x04+4]); 3620 outb(GDCIDX, 0x04); outb(GDCREG, modetable[0x04+55]); 3621 outb(GDCIDX, 0x05); outb(GDCREG, modetable[0x05+55]); 3622 outb(GDCIDX, 0x06); outb(GDCREG, modetable[0x06+55]); 3623 if (crtc_addr == MONO_BASE) { 3624 outb(GDCIDX, 0x06); outb(GDCREG,(modetable[0x06+55] & 0x03) | 0x08); 3625 } 3626 else { 3627 outb(GDCIDX, 0x06); outb(GDCREG,(modetable[0x06+55] & 0x03) | 0x0c); 3628 } 3629#else 3630 outw(TSIDX, 0x0002 | (modetable[0x02+4]<<8)); 3631 outw(TSIDX, 0x0004 | (modetable[0x04+4]<<8)); 3632 outw(GDCIDX, 0x0004 | (modetable[0x04+55]<<8)); 3633 outw(GDCIDX, 0x0005 | (modetable[0x05+55]<<8)); 3634 if (crtc_addr == MONO_BASE) 3635 outw(GDCIDX, 0x0006 | (((modetable[0x06+55] & 0x03) | 0x08)<<8)); 3636 else 3637 outw(GDCIDX, 0x0006 | (((modetable[0x06+55] & 0x03) | 0x0c)<<8)); 3638#endif 3639 splx(s); 3640} 3641 3642void 3643copy_font(int operation, int font_type, char* font_image) 3644{ 3645 int ch, line, segment, fontsize; 3646 u_char val; 3647 3648 /* dont mess with console we dont know video mode on */ 3649 if (cur_console->status & UNKNOWN_MODE) 3650 return; 3651 3652 switch (font_type) { 3653 default: 3654 case FONT_8: 3655 segment = 0x8000; 3656 fontsize = 8; 3657 break; 3658 case FONT_14: 3659 segment = 0x4000; 3660 fontsize = 14; 3661 break; 3662 case FONT_16: 3663 segment = 0x0000; 3664 fontsize = 16; 3665 break; 3666 } 3667 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 3668 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 3669 set_font_mode(); 3670 for (ch=0; ch < 256; ch++) 3671 for (line=0; line < fontsize; line++) 3672 if (operation) 3673 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) = 3674 font_image[(ch*fontsize)+line]; 3675 else 3676 font_image[(ch*fontsize)+line] = 3677 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line); 3678 set_normal_mode(); 3679 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ 3680} 3681 3682static void 3683set_destructive_cursor(scr_stat *scp) 3684{ 3685 u_char cursor[32]; 3686 caddr_t address; 3687 int i; 3688 char *font_buffer; 3689 3690 3691 if (scp->font_size < 14) { 3692 font_buffer = font_8; 3693 address = (caddr_t)VIDEOMEM + 0x8000; 3694 } 3695 else if (scp->font_size >= 16) { 3696 font_buffer = font_16; 3697 address = (caddr_t)VIDEOMEM; 3698 } 3699 else { 3700 font_buffer = font_14; 3701 address = (caddr_t)VIDEOMEM + 0x4000; 3702 } 3703 3704 if (scp->status & MOUSE_VISIBLE) { 3705 if ((scp->cursor_saveunder & 0xff) == 0xd0) 3706 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 3707 else if ((scp->cursor_saveunder & 0xff) == 0xd1) 3708 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 3709 else if ((scp->cursor_saveunder & 0xff) == 0xd2) 3710 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 3711 else if ((scp->cursor_saveunder & 0xff) == 0xd3) 3712 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 3713 else 3714 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 3715 cursor, scp->font_size); 3716 } 3717 else 3718 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 3719 cursor, scp->font_size); 3720 for (i=0; i<32; i++) 3721 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 3722 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 3723 cursor[i] |= 0xff; 3724#if 1 3725 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 3726#endif 3727 set_font_mode(); 3728 sc_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); 3729 set_normal_mode(); 3730} 3731 3732static void 3733set_mouse_pos(scr_stat *scp) 3734{ 3735 static int last_xpos = -1, last_ypos = -1; 3736 /* 3737 * the margins imposed here are not ideal, we loose 3738 * a couble of pixels on the borders.. 3739 */ 3740 if (scp->mouse_xpos < 0) 3741 scp->mouse_xpos = 0; 3742 if (scp->mouse_ypos < 0) 3743 scp->mouse_ypos = 0; 3744 if (scp->mouse_xpos > (scp->xsize*8)-2) 3745 scp->mouse_xpos = (scp->xsize*8)-2; 3746 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-2) 3747 scp->mouse_ypos = (scp->ysize*scp->font_size)-2; 3748 3749 if (scp->status & UNKNOWN_MODE) 3750 return; 3751 3752 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 3753 scp->status |= MOUSE_MOVED; 3754 3755 scp->mouse_pos = scp->scr_buf + 3756 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 3757 3758 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) { 3759 u_short *ptr; 3760 int i = 0; 3761 3762 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 3763 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 3764 scp->mouse_cut_end = scp->mouse_pos; 3765 for (ptr = (scp->mouse_cut_start > scp->mouse_cut_end 3766 ? scp->mouse_cut_end : scp->mouse_cut_start); 3767 ptr <= (scp->mouse_cut_start > scp->mouse_cut_end 3768 ? scp->mouse_cut_start : scp->mouse_cut_end); 3769 ptr++) { 3770 cut_buffer[i++] = *ptr & 0xff; 3771 if (((ptr - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 3772 cut_buffer[i++] = '\n'; 3773 } 3774 } 3775 cut_buffer[i] = 0x00; 3776 } 3777 } 3778} 3779 3780static void 3781mouse_cut_start(scr_stat *scp) 3782{ 3783 int i; 3784 3785 if (scp->status & MOUSE_VISIBLE) { 3786 if (scp->mouse_pos == scp->mouse_cut_start && 3787 scp->mouse_cut_start == scp->mouse_cut_end) { 3788 cut_buffer[0] = 0x00; 3789 remove_cutmarking(scp); 3790 } 3791 else { 3792 scp->mouse_cut_start = scp->mouse_cut_end = scp->mouse_pos; 3793 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 3794 cut_buffer[1] = 0x00; 3795 scp->status |= MOUSE_CUTTING; 3796 } 3797 mark_all(scp); 3798 /* delete all other screens cut markings */ 3799 for (i=0; i<MAXCONS; i++) { 3800 if (console[i] == NULL || console[i] == scp) 3801 continue; 3802 remove_cutmarking(console[i]); 3803 } 3804 } 3805} 3806 3807static void 3808mouse_cut_end(scr_stat *scp) 3809{ 3810 if (scp->status & MOUSE_VISIBLE) { 3811 scp->status &= ~MOUSE_CUTTING; 3812 } 3813} 3814 3815static void 3816mouse_paste(scr_stat *scp) 3817{ 3818 if (scp->status & MOUSE_VISIBLE) { 3819 struct tty *tp; 3820 u_char *ptr = cut_buffer; 3821 3822 tp = VIRTUAL_TTY(get_scr_num()); 3823 while (*ptr) 3824 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 3825 } 3826} 3827 3828static void 3829draw_mouse_image(scr_stat *scp) 3830{ 3831 caddr_t address; 3832 int i; 3833 char *font_buffer; 3834 u_short buffer[32]; 3835 u_short xoffset, yoffset; 3836 u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf); 3837 int font_size = scp->font_size; 3838 3839 if (font_size < 14) { 3840 font_buffer = font_8; 3841 address = (caddr_t)VIDEOMEM + 0x8000; 3842 } 3843 else if (font_size >= 16) { 3844 font_buffer = font_16; 3845 address = (caddr_t)VIDEOMEM; 3846 } 3847 else { 3848 font_buffer = font_14; 3849 address = (caddr_t)VIDEOMEM + 0x4000; 3850 } 3851 xoffset = scp->mouse_xpos % 8; 3852 yoffset = scp->mouse_ypos % font_size; 3853 3854 /* prepare mousepointer char's bitmaps */ 3855 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 3856 &scp->mouse_cursor[0], font_size); 3857 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 3858 &scp->mouse_cursor[32], font_size); 3859 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 3860 &scp->mouse_cursor[64], font_size); 3861 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 3862 &scp->mouse_cursor[96], font_size); 3863 for (i=0; i<font_size; i++) { 3864 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 3865 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 3866 } 3867 3868 /* now and-or in the mousepointer image */ 3869 for (i=0; i<16; i++) { 3870 buffer[i+yoffset] = 3871 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 3872 | (mouse_or_mask[i] >> xoffset); 3873 } 3874 for (i=0; i<font_size; i++) { 3875 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 3876 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 3877 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 3878 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 3879 } 3880 3881 scp->mouse_oldpos = scp->mouse_pos; 3882 3883 /* wait for vertical retrace to avoid jitter on some videocards */ 3884#if 1 3885 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 3886#endif 3887 set_font_mode(); 3888 sc_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); 3889 set_normal_mode(); 3890 *(crt_pos) = (*(scp->mouse_pos)&0xff00)|0xd0; 3891 *(crt_pos+scp->xsize) = (*(scp->mouse_pos+scp->xsize)&0xff00)|0xd2; 3892 if (scp->mouse_xpos < (scp->xsize-1)*8) { 3893 *(crt_pos+1) = (*(scp->mouse_pos+1)&0xff00)|0xd1; 3894 *(crt_pos+scp->xsize+1) = (*(scp->mouse_pos+scp->xsize+1)&0xff00)|0xd3; 3895 } 3896 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 3897 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 3898} 3899 3900static void 3901remove_mouse_image(scr_stat *scp) 3902{ 3903 u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf); 3904 3905 *(crt_pos) = *(scp->mouse_oldpos); 3906 *(crt_pos+1) = *(scp->mouse_oldpos+1); 3907 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 3908 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 3909 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 3910 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 3911} 3912 3913static void 3914draw_cutmarking(scr_stat *scp) 3915{ 3916 u_short *ptr; 3917 u_short och, nch; 3918 3919 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 3920 nch = och = *(Crtat + (ptr - scp->scr_buf)); 3921 /* are we outside the selected area ? */ 3922 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 3923 scp->mouse_cut_end : scp->mouse_cut_start) || 3924 ptr > (scp->mouse_cut_start > scp->mouse_cut_end ? 3925 scp->mouse_cut_start : scp->mouse_cut_end)) { 3926 if (ptr != scp->cursor_pos) 3927 nch = (och & 0xff) | (*ptr & 0xff00); 3928 } 3929 else { 3930 /* are we clear of the cursor image ? */ 3931 if (ptr != scp->cursor_pos) 3932 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 3933 else { 3934 if (flags & CHAR_CURSOR) 3935 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 3936 else 3937 if (!(flags & BLINK_CURSOR)) 3938 nch = (och & 0xff) | (*ptr & 0xff00); 3939 } 3940 } 3941 if (nch != och) 3942 *(Crtat + (ptr - scp->scr_buf)) = nch; 3943 } 3944} 3945 3946static void 3947remove_cutmarking(scr_stat *scp) 3948{ 3949 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3950 scp->status &= ~MOUSE_CUTTING; 3951 mark_all(scp); 3952} 3953 3954static void 3955save_palette(void) 3956{ 3957 int i; 3958 3959 outb(PALRADR, 0x00); 3960 for (i=0x00; i<0x300; i++) 3961 palette[i] = inb(PALDATA); 3962 inb(crtc_addr+6); /* reset flip/flop */ 3963} 3964 3965void 3966load_palette(char *palette) 3967{ 3968 int i; 3969 3970 outb(PIXMASK, 0xFF); /* no pixelmask */ 3971 outb(PALWADR, 0x00); 3972 for (i=0x00; i<0x300; i++) 3973 outb(PALDATA, palette[i]); 3974 inb(crtc_addr+6); /* reset flip/flop */ 3975 outb(ATC, 0x20); /* enable palette */ 3976} 3977 3978static void 3979do_bell(scr_stat *scp, int pitch, int duration) 3980{ 3981 if (flags & VISUAL_BELL) { 3982 if (blink_in_progress) 3983 return; 3984 blink_in_progress = 4; 3985 if (scp != cur_console) 3986 blink_in_progress += 2; 3987 blink_screen(cur_console); 3988 } else { 3989 if (scp != cur_console) 3990 pitch *= 2; 3991 sysbeep(pitch, duration); 3992 } 3993} 3994 3995static void 3996blink_screen(void *arg) 3997{ 3998 scr_stat *scp = arg; 3999 4000 if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) { 4001 blink_in_progress = FALSE; 4002 mark_all(scp); 4003 if (delayed_next_scr) 4004 switch_scr(scp, delayed_next_scr - 1); 4005 } 4006 else { 4007 if (blink_in_progress & 1) 4008 fillw(kernel_default.std_color | scr_map[0x20], 4009 Crtat, scp->xsize * scp->ysize); 4010 else 4011 fillw(kernel_default.rev_color | scr_map[0x20], 4012 Crtat, scp->xsize * scp->ysize); 4013 blink_in_progress--; 4014 timeout(blink_screen, scp, hz / 10); 4015 } 4016} 4017 4018#ifdef SC_SPLASH_SCREEN 4019static void 4020toggle_splash_screen(scr_stat *scp) 4021{ 4022 static int toggle = 0; 4023 static u_char save_mode; 4024 int s; 4025 4026 if (video_mode_ptr == NULL) 4027 return; 4028 4029 s = splhigh(); 4030 if (toggle) { 4031 scp->mode = save_mode; 4032 scp->status &= ~UNKNOWN_MODE; 4033 set_mode(scp); 4034 load_palette(palette); 4035 toggle = 0; 4036 } 4037 else { 4038 save_mode = scp->mode; 4039 scp->mode = M_VGA_CG320; 4040 scp->status |= UNKNOWN_MODE; 4041 set_mode(scp); 4042 /* load image */ 4043 toggle = 1; 4044 } 4045 splx(s); 4046} 4047#endif 4048#endif /* NSC */ 4049