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