syscons.c revision 20197
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.190 1996/12/01 19:05:47 sos 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 if (crtc_vga) 2433 if (crtc_addr == MONO_BASE) 2434 scp->mode = M_VGA_M80x25; 2435 else 2436 scp->mode = M_VGA_C80x25; 2437 else 2438 if (crtc_addr == MONO_BASE) 2439 scp->mode = M_B80x25; 2440 else 2441 scp->mode = M_C80x25; 2442 2443 scp->font_size = FONT_16; 2444 scp->xsize = COL; 2445 scp->ysize = ROW; 2446 scp->start = scp->xsize * scp->ysize; 2447 scp->end = 0; 2448 scp->term.esc = 0; 2449 scp->term.attr_mask = NORMAL_ATTR; 2450 scp->term.cur_attr = 2451 scp->term.cur_color = scp->term.std_color = 2452 current_default->std_color; 2453 scp->term.rev_color = current_default->rev_color; 2454 scp->border = BG_BLACK; 2455 scp->cursor_start = *(char *)pa_to_va(0x461); 2456 scp->cursor_end = *(char *)pa_to_va(0x460); 2457 scp->mouse_xpos = scp->xsize*8/2; 2458 scp->mouse_ypos = scp->ysize*scp->font_size/2; 2459 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 2460 scp->mouse_signal = 0; 2461 scp->mouse_pid = 0; 2462 scp->mouse_proc = NULL; 2463 scp->bell_pitch = BELL_PITCH; 2464 scp->bell_duration = BELL_DURATION; 2465 scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 2466 scp->status |= CURSOR_ENABLED; 2467 scp->pid = 0; 2468 scp->proc = NULL; 2469 scp->smode.mode = VT_AUTO; 2470 scp->history_head = scp->history_pos = scp->history = NULL; 2471 scp->history_size = HISTORY_SIZE; 2472} 2473 2474static u_char 2475*get_fstr(u_int c, u_int *len) 2476{ 2477 u_int i; 2478 2479 if (!(c & FKEY)) 2480 return(NULL); 2481 i = (c & 0xFF) - F_FN; 2482 if (i > n_fkey_tab) 2483 return(NULL); 2484 *len = fkey_tab[i].len; 2485 return(fkey_tab[i].str); 2486} 2487 2488static void 2489history_to_screen(scr_stat *scp) 2490{ 2491 int i; 2492 2493 for (i=0; i<scp->ysize; i++) 2494 bcopyw(scp->history + (((scp->history_pos - scp->history) + 2495 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 2496 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 2497 scp->xsize * sizeof(u_short)); 2498 mark_all(scp); 2499} 2500 2501static int 2502history_up_line(scr_stat *scp) 2503{ 2504 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 2505 scp->history_head) { 2506 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 2507 history_to_screen(scp); 2508 return 0; 2509 } 2510 else 2511 return -1; 2512} 2513 2514static int 2515history_down_line(scr_stat *scp) 2516{ 2517 if (scp->history_pos != scp->history_head) { 2518 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 2519 history_to_screen(scp); 2520 return 0; 2521 } 2522 else 2523 return -1; 2524} 2525 2526/* 2527 * scgetc(flags) - get character from keyboard. 2528 * If flags & SCGETC_CN, then avoid harmful side effects. 2529 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 2530 * return NOKEY if there is nothing there. 2531 */ 2532static u_int 2533scgetc(u_int flags) 2534{ 2535 struct key_t *key; 2536 u_char scancode, keycode; 2537 u_int state, action; 2538 int c; 2539 static u_char esc_flag = 0, compose = 0; 2540 static u_int chr = 0; 2541 2542next_code: 2543 /* first see if there is something in the keyboard port */ 2544 if (flags & SCGETC_NONBLOCK) { 2545 c = read_kbd_data_no_wait(sc_port); 2546 if (c == -1) 2547 return(NOKEY); 2548 } else { 2549 do { 2550 c = read_kbd_data(sc_port); 2551 } while(c == -1); 2552 } 2553 scancode = (u_char)c; 2554 2555 /* do the /dev/random device a favour */ 2556 if (!(flags & SCGETC_CN)) 2557 add_keyboard_randomness(scancode); 2558 2559 if (cur_console->status & KBD_RAW_MODE) 2560 return scancode; 2561 2562 keycode = scancode & 0x7F; 2563 switch (esc_flag) { 2564 case 0x00: /* normal scancode */ 2565 switch(scancode) { 2566 case 0xB8: /* left alt (compose key) */ 2567 if (compose) { 2568 compose = 0; 2569 if (chr > 255) { 2570 do_bell(cur_console, 2571 BELL_PITCH, BELL_DURATION); 2572 chr = 0; 2573 } 2574 } 2575 break; 2576 case 0x38: 2577 if (!compose) { 2578 compose = 1; 2579 chr = 0; 2580 } 2581 break; 2582 case 0xE0: 2583 case 0xE1: 2584 esc_flag = scancode; 2585 goto next_code; 2586 } 2587 break; 2588 case 0xE0: /* 0xE0 prefix */ 2589 esc_flag = 0; 2590 switch (keycode) { 2591 case 0x1C: /* right enter key */ 2592 keycode = 0x59; 2593 break; 2594 case 0x1D: /* right ctrl key */ 2595 keycode = 0x5A; 2596 break; 2597 case 0x35: /* keypad divide key */ 2598 keycode = 0x5B; 2599 break; 2600 case 0x37: /* print scrn key */ 2601 keycode = 0x5C; 2602 break; 2603 case 0x38: /* right alt key (alt gr) */ 2604 keycode = 0x5D; 2605 break; 2606 case 0x47: /* grey home key */ 2607 keycode = 0x5E; 2608 break; 2609 case 0x48: /* grey up arrow key */ 2610 keycode = 0x5F; 2611 break; 2612 case 0x49: /* grey page up key */ 2613 keycode = 0x60; 2614 break; 2615 case 0x4B: /* grey left arrow key */ 2616 keycode = 0x61; 2617 break; 2618 case 0x4D: /* grey right arrow key */ 2619 keycode = 0x62; 2620 break; 2621 case 0x4F: /* grey end key */ 2622 keycode = 0x63; 2623 break; 2624 case 0x50: /* grey down arrow key */ 2625 keycode = 0x64; 2626 break; 2627 case 0x51: /* grey page down key */ 2628 keycode = 0x65; 2629 break; 2630 case 0x52: /* grey insert key */ 2631 keycode = 0x66; 2632 break; 2633 case 0x53: /* grey delete key */ 2634 keycode = 0x67; 2635 break; 2636 2637 /* the following 3 are only used on the MS "Natural" keyboard */ 2638 case 0x5b: /* left Window key */ 2639 keycode = 0x69; 2640 break; 2641 case 0x5c: /* right Window key */ 2642 keycode = 0x6a; 2643 break; 2644 case 0x5d: /* menu key */ 2645 keycode = 0x6b; 2646 break; 2647 default: /* ignore everything else */ 2648 goto next_code; 2649 } 2650 break; 2651 case 0xE1: /* 0xE1 prefix */ 2652 esc_flag = 0; 2653 if (keycode == 0x1D) 2654 esc_flag = 0x1D; 2655 goto next_code; 2656 /* NOT REACHED */ 2657 case 0x1D: /* pause / break */ 2658 esc_flag = 0; 2659 if (keycode != 0x45) 2660 goto next_code; 2661 keycode = 0x68; 2662 break; 2663 } 2664 2665 /* if scroll-lock pressed allow history browsing */ 2666 if (cur_console->history && cur_console->status & SLKED) { 2667 int i; 2668 2669 cur_console->status &= ~CURSOR_ENABLED; 2670 if (!(cur_console->status & BUFFER_SAVED)) { 2671 cur_console->status |= BUFFER_SAVED; 2672 cur_console->history_save = cur_console->history_head; 2673 2674 /* copy screen into top of history buffer */ 2675 for (i=0; i<cur_console->ysize; i++) { 2676 bcopyw(cur_console->scr_buf + (cur_console->xsize * i), 2677 cur_console->history_head, 2678 cur_console->xsize * sizeof(u_short)); 2679 cur_console->history_head += cur_console->xsize; 2680 if (cur_console->history_head + cur_console->xsize > 2681 cur_console->history + cur_console->history_size) 2682 cur_console->history_head=cur_console->history; 2683 } 2684 cur_console->history_pos = cur_console->history_head; 2685 history_to_screen(cur_console); 2686 } 2687 switch (scancode) { 2688 case 0x47: /* home key */ 2689 cur_console->history_pos = cur_console->history_head; 2690 history_to_screen(cur_console); 2691 goto next_code; 2692 2693 case 0x4F: /* end key */ 2694 cur_console->history_pos = 2695 WRAPHIST(cur_console, cur_console->history_head, 2696 cur_console->xsize*cur_console->ysize); 2697 history_to_screen(cur_console); 2698 goto next_code; 2699 2700 case 0x48: /* up arrow key */ 2701 if (history_up_line(cur_console)) 2702 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2703 goto next_code; 2704 2705 case 0x50: /* down arrow key */ 2706 if (history_down_line(cur_console)) 2707 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2708 goto next_code; 2709 2710 case 0x49: /* page up key */ 2711 for (i=0; i<cur_console->ysize; i++) 2712 if (history_up_line(cur_console)) { 2713 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2714 break; 2715 } 2716 goto next_code; 2717 2718 case 0x51: /* page down key */ 2719 for (i=0; i<cur_console->ysize; i++) 2720 if (history_down_line(cur_console)) { 2721 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2722 break; 2723 } 2724 goto next_code; 2725 } 2726 } 2727 2728 if (compose) { 2729 switch (scancode) { 2730 /* key pressed process it */ 2731 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 2732 chr = (scancode - 0x40) + chr*10; 2733 goto next_code; 2734 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 2735 chr = (scancode - 0x47) + chr*10; 2736 goto next_code; 2737 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 2738 chr = (scancode - 0x4E) + chr*10; 2739 goto next_code; 2740 case 0x52: /* keypad 0 */ 2741 chr *= 10; 2742 goto next_code; 2743 2744 /* key release, no interest here */ 2745 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 2746 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 2747 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 2748 case 0xD2: /* keypad 0 */ 2749 goto next_code; 2750 2751 case 0x38: /* left alt key */ 2752 break; 2753 default: 2754 if (chr) { 2755 compose = chr = 0; 2756 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2757 goto next_code; 2758 } 2759 break; 2760 } 2761 } 2762 2763 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2764 if ((!agrs && (cur_console->status & ALKED)) 2765 || (agrs && !(cur_console->status & ALKED))) 2766 keycode += ALTGR_OFFSET; 2767 key = &key_map.key[keycode]; 2768 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2769 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2770 state ^= 1; 2771 2772 /* Check for make/break */ 2773 action = key->map[state]; 2774 if (scancode & 0x80) { /* key released */ 2775 if (key->spcl & 0x80) { 2776 switch (action) { 2777 case LSH: 2778 shfts &= ~1; 2779 break; 2780 case RSH: 2781 shfts &= ~2; 2782 break; 2783 case LCTR: 2784 ctls &= ~1; 2785 break; 2786 case RCTR: 2787 ctls &= ~2; 2788 break; 2789 case LALT: 2790 alts &= ~1; 2791 break; 2792 case RALT: 2793 alts &= ~2; 2794 break; 2795 case NLK: 2796 nlkcnt = 0; 2797 break; 2798 case CLK: 2799 clkcnt = 0; 2800 break; 2801 case SLK: 2802 slkcnt = 0; 2803 break; 2804 case ASH: 2805 agrs = 0; 2806 break; 2807 case ALK: 2808 alkcnt = 0; 2809 break; 2810 case META: 2811 metas = 0; 2812 break; 2813 } 2814 } 2815 if (chr && !compose) { 2816 action = chr; 2817 chr = 0; 2818 return(action); 2819 } 2820 } else { 2821 /* key pressed */ 2822 if (key->spcl & (0x80>>state)) { 2823 switch (action) { 2824 /* LOCKING KEYS */ 2825 case NLK: 2826#ifdef SC_SPLASH_SCREEN 2827 toggle_splash_screen(cur_console); /* SOS XXX */ 2828#endif 2829 if (!nlkcnt) { 2830 nlkcnt++; 2831 if (cur_console->status & NLKED) 2832 cur_console->status &= ~NLKED; 2833 else 2834 cur_console->status |= NLKED; 2835 update_leds(cur_console->status); 2836 } 2837 break; 2838 case CLK: 2839 if (!clkcnt) { 2840 clkcnt++; 2841 if (cur_console->status & CLKED) 2842 cur_console->status &= ~CLKED; 2843 else 2844 cur_console->status |= CLKED; 2845 update_leds(cur_console->status); 2846 } 2847 break; 2848 case SLK: 2849 if (!slkcnt) { 2850 slkcnt++; 2851 if (cur_console->status & SLKED) { 2852 cur_console->status &= ~SLKED; 2853 if (cur_console->status & BUFFER_SAVED){ 2854 int i; 2855 u_short *ptr = cur_console->history_save; 2856 2857 for (i=0; i<cur_console->ysize; i++) { 2858 bcopyw(ptr, 2859 cur_console->scr_buf + 2860 (cur_console->xsize*i), 2861 cur_console->xsize * sizeof(u_short)); 2862 ptr += cur_console->xsize; 2863 if (ptr + cur_console->xsize > 2864 cur_console->history + 2865 cur_console->history_size) 2866 ptr = cur_console->history; 2867 } 2868 cur_console->status &= ~BUFFER_SAVED; 2869 cur_console->history_head=cur_console->history_save; 2870 cur_console->status |= CURSOR_ENABLED; 2871 mark_all(cur_console); 2872 } 2873 scstart(VIRTUAL_TTY(get_scr_num())); 2874 } 2875 else 2876 cur_console->status |= SLKED; 2877 update_leds(cur_console->status); 2878 } 2879 break; 2880 case ALK: 2881 if (!alkcnt) { 2882 alkcnt++; 2883 if (cur_console->status & ALKED) 2884 cur_console->status &= ~ALKED; 2885 else 2886 cur_console->status |= ALKED; 2887 update_leds(cur_console->status); 2888 } 2889 break; 2890 2891 /* NON-LOCKING KEYS */ 2892 case NOP: 2893 break; 2894 case SPSC: 2895#ifdef SC_SPLASH_SCREEN 2896 toggle_splash_screen(cur_console); 2897#endif 2898 break; 2899 case RBT: 2900 shutdown_nice(); 2901 break; 2902 case SUSP: 2903#if NAPM > 0 2904 apm_suspend(); 2905#endif 2906 break; 2907 2908 case DBG: 2909#ifdef DDB /* try to switch to console 0 */ 2910 if (cur_console->smode.mode == VT_AUTO && 2911 console[0]->smode.mode == VT_AUTO) 2912 switch_scr(cur_console, 0); 2913 Debugger("manual escape to debugger"); 2914#else 2915 printf("No debugger in kernel\n"); 2916#endif 2917 break; 2918 case LSH: 2919 shfts |= 1; 2920 break; 2921 case RSH: 2922 shfts |= 2; 2923 break; 2924 case LCTR: 2925 ctls |= 1; 2926 break; 2927 case RCTR: 2928 ctls |= 2; 2929 break; 2930 case LALT: 2931 alts |= 1; 2932 break; 2933 case RALT: 2934 alts |= 2; 2935 break; 2936 case ASH: 2937 agrs = 1; 2938 break; 2939 case META: 2940 metas = 1; 2941 break; 2942 case NEXT: 2943 switch_scr(cur_console, (get_scr_num() + 1) % MAXCONS); 2944 break; 2945 case BTAB: 2946 return(BKEY); 2947 default: 2948 if (action >= F_SCR && action <= L_SCR) { 2949 switch_scr(cur_console, action - F_SCR); 2950 break; 2951 } 2952 if (action >= F_FN && action <= L_FN) 2953 action |= FKEY; 2954 return(action); 2955 } 2956 } 2957 else { 2958 if (metas) 2959 action |= MKEY; 2960 return(action); 2961 } 2962 } 2963 goto next_code; 2964} 2965 2966int 2967scmmap(dev_t dev, int offset, int nprot) 2968{ 2969 if (offset > 0x20000 - PAGE_SIZE) 2970 return -1; 2971 return i386_btop((VIDEOMEM + offset)); 2972} 2973 2974/* 2975 * Calculate hardware attributes word using logical attributes mask and 2976 * hardware colors 2977 */ 2978 2979static int 2980mask2attr(struct term_stat *term) 2981{ 2982 int attr, mask = term->attr_mask; 2983 2984 if (mask & REVERSE_ATTR) { 2985 attr = ((mask & FOREGROUND_CHANGED) ? 2986 ((term->cur_color & 0xF000) >> 4) : 2987 (term->rev_color & 0x0F00)) | 2988 ((mask & BACKGROUND_CHANGED) ? 2989 ((term->cur_color & 0x0F00) << 4) : 2990 (term->rev_color & 0xF000)); 2991 } else 2992 attr = term->cur_color; 2993 2994 /* XXX: underline mapping for Hercules adapter can be better */ 2995 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 2996 attr ^= 0x0800; 2997 if (mask & BLINK_ATTR) 2998 attr ^= 0x8000; 2999 3000 return attr; 3001} 3002 3003static void 3004update_leds(int which) 3005{ 3006 int s; 3007 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 3008 3009 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 3010 if (key_map.n_keys > ALTGR_OFFSET) { 3011 if (which & ALKED) 3012 which |= CLKED; 3013 else 3014 which &= ~CLKED; 3015 } 3016 3017 s = spltty(); 3018 send_kbd_command_and_data(sc_port, KBDC_SET_LEDS, 3019 xlate_leds[which & LED_MASK]); 3020 splx(s); 3021} 3022 3023void 3024set_mode(scr_stat *scp) 3025{ 3026 char *modetable; 3027 char special_modetable[64]; 3028 3029 if (scp != cur_console) 3030 return; 3031 3032 /* setup video hardware for the given mode */ 3033 switch (scp->mode) { 3034 case M_VGA_M80x60: 3035 bcopyw(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 3036 goto special_80x60; 3037 3038 case M_VGA_C80x60: 3039 bcopyw(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 3040special_80x60: 3041 special_modetable[2] = 0x08; 3042 special_modetable[19] = 0x47; 3043 goto special_480l; 3044 3045 case M_VGA_M80x30: 3046 bcopyw(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 3047 goto special_80x30; 3048 3049 case M_VGA_C80x30: 3050 bcopyw(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 3051special_80x30: 3052 special_modetable[19] = 0x4f; 3053special_480l: 3054 special_modetable[9] |= 0xc0; 3055 special_modetable[16] = 0x08; 3056 special_modetable[17] = 0x3e; 3057 special_modetable[26] = 0xea; 3058 special_modetable[28] = 0xdf; 3059 special_modetable[31] = 0xe7; 3060 special_modetable[32] = 0x04; 3061 modetable = special_modetable; 3062 goto setup_mode; 3063 3064 case M_ENH_B80x43: 3065 bcopyw(video_mode_ptr+(64*M_ENH_B80x25), &special_modetable, 64); 3066 goto special_80x43; 3067 3068 case M_ENH_C80x43: 3069 bcopyw(video_mode_ptr+(64*M_ENH_C80x25), &special_modetable, 64); 3070special_80x43: 3071 special_modetable[28] = 87; 3072 goto special_80x50; 3073 3074 case M_VGA_M80x50: 3075 bcopyw(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 3076 goto special_80x50; 3077 3078 case M_VGA_C80x50: 3079 bcopyw(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 3080special_80x50: 3081 special_modetable[2] = 8; 3082 special_modetable[19] = 7; 3083 modetable = special_modetable; 3084 goto setup_mode; 3085 3086 case M_VGA_C40x25: case M_VGA_C80x25: 3087 case M_VGA_M80x25: 3088 case M_B40x25: case M_C40x25: 3089 case M_B80x25: case M_C80x25: 3090 case M_ENH_B40x25: case M_ENH_C40x25: 3091 case M_ENH_B80x25: case M_ENH_C80x25: 3092 3093 modetable = video_mode_ptr + (scp->mode * 64); 3094setup_mode: 3095 set_vgaregs(modetable); 3096 scp->font_size = *(modetable + 2); 3097 3098 /* set font type (size) */ 3099 if (scp->font_size < FONT_14) { 3100 if (fonts_loaded & FONT_8) 3101 copy_font(LOAD, FONT_8, font_8); 3102 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 3103 } else if (scp->font_size >= FONT_16) { 3104 if (fonts_loaded & FONT_16) 3105 copy_font(LOAD, FONT_16, font_16); 3106 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 3107 } else { 3108 if (fonts_loaded & FONT_14) 3109 copy_font(LOAD, FONT_14, font_14); 3110 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 3111 } 3112 if (flags & CHAR_CURSOR) 3113 set_destructive_cursor(scp); 3114 mark_all(scp); 3115 break; 3116 3117 case M_BG320: case M_CG320: case M_BG640: 3118 case M_CG320_D: case M_CG640_E: 3119 case M_CG640x350: case M_ENH_CG640: 3120 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 3121 3122 set_vgaregs(video_mode_ptr + (scp->mode * 64)); 3123 scp->font_size = FONT_NONE; 3124 break; 3125 3126 default: 3127 /* call user defined function XXX */ 3128 break; 3129 } 3130 3131 /* set border color for this (virtual) console */ 3132 set_border(scp->border); 3133 return; 3134} 3135 3136void 3137set_border(u_char color) 3138{ 3139 inb(crtc_addr+6); /* reset flip-flop */ 3140 outb(ATC, 0x11); outb(ATC, color); 3141 inb(crtc_addr+6); /* reset flip-flop */ 3142 outb(ATC, 0x20); /* enable Palette */ 3143} 3144 3145static void 3146set_vgaregs(char *modetable) 3147{ 3148 int i, s = splhigh(); 3149 3150 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 3151 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 3152 for (i=0; i<4; i++) { /* program sequencer */ 3153 outb(TSIDX, i+1); 3154 outb(TSREG, modetable[i+5]); 3155 } 3156 outb(MISC, modetable[9]); /* set dot-clock */ 3157 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 3158 outb(crtc_addr, 0x11); 3159 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 3160 for (i=0; i<25; i++) { /* program crtc */ 3161 outb(crtc_addr, i); 3162 if (i == 14 || i == 15) /* no hardware cursor */ 3163 outb(crtc_addr+1, 0xff); 3164 else 3165 outb(crtc_addr+1, modetable[i+10]); 3166 } 3167 inb(crtc_addr+6); /* reset flip-flop */ 3168 for (i=0; i<20; i++) { /* program attribute ctrl */ 3169 outb(ATC, i); 3170 outb(ATC, modetable[i+35]); 3171 } 3172 for (i=0; i<9; i++) { /* program graph data ctrl */ 3173 outb(GDCIDX, i); 3174 outb(GDCREG, modetable[i+55]); 3175 } 3176 inb(crtc_addr+6); /* reset flip-flop */ 3177 outb(ATC, 0x20); /* enable palette */ 3178 splx(s); 3179} 3180 3181static void 3182set_font_mode() 3183{ 3184 /* setup vga for loading fonts (graphics plane mode) */ 3185 inb(crtc_addr+6); /* reset flip-flop */ 3186 outb(ATC, 0x10); outb(ATC, 0x01); 3187 inb(crtc_addr+6); /* reset flip-flop */ 3188 outb(ATC, 0x20); /* enable palette */ 3189#if SLOW_VGA 3190 outb(TSIDX, 0x02); outb(TSREG, 0x04); 3191 outb(TSIDX, 0x04); outb(TSREG, 0x06); 3192 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 3193 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 3194 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); 3195#else 3196 outw(TSIDX, 0x0402); 3197 outw(TSIDX, 0x0604); 3198 outw(GDCIDX, 0x0204); 3199 outw(GDCIDX, 0x0005); 3200 outw(GDCIDX, 0x0506); /* addr = a0000, 64kb */ 3201#endif 3202} 3203 3204static void 3205set_normal_mode() 3206{ 3207 char *modetable; 3208 int s = splhigh(); 3209 3210 switch (cur_console->mode) { 3211 case M_VGA_M80x60: 3212 case M_VGA_M80x50: 3213 case M_VGA_M80x30: 3214 modetable = video_mode_ptr + (64*M_VGA_M80x25); 3215 break; 3216 3217 case M_VGA_C80x60: 3218 case M_VGA_C80x50: 3219 case M_VGA_C80x30: 3220 modetable = video_mode_ptr + (64*M_VGA_C80x25); 3221 break; 3222 3223 case M_ENH_B80x43: 3224 modetable = video_mode_ptr + (64*M_ENH_B80x25); 3225 break; 3226 3227 case M_ENH_C80x43: 3228 modetable = video_mode_ptr + (64*M_ENH_C80x25); 3229 break; 3230 3231 case M_VGA_C40x25: case M_VGA_C80x25: 3232 case M_VGA_M80x25: 3233 case M_B40x25: case M_C40x25: 3234 case M_B80x25: case M_C80x25: 3235 case M_ENH_B40x25: case M_ENH_C40x25: 3236 case M_ENH_B80x25: case M_ENH_C80x25: 3237 3238 case M_BG320: case M_CG320: case M_BG640: 3239 case M_CG320_D: case M_CG640_E: 3240 case M_CG640x350: case M_ENH_CG640: 3241 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 3242 modetable = video_mode_ptr + (cur_console->mode * 64); 3243 3244 default: 3245 modetable = video_mode_ptr + (64*M_VGA_C80x25); 3246 } 3247 3248 /* setup vga for normal operation mode again */ 3249 inb(crtc_addr+6); /* reset flip-flop */ 3250 outb(ATC, 0x10); outb(ATC, modetable[0x10+35]); 3251 inb(crtc_addr+6); /* reset flip-flop */ 3252 outb(ATC, 0x20); /* enable palette */ 3253#if SLOW_VGA 3254 outb(TSIDX, 0x02); outb(TSREG, modetable[0x02+4]); 3255 outb(TSIDX, 0x04); outb(TSREG, modetable[0x04+4]); 3256 outb(GDCIDX, 0x04); outb(GDCREG, modetable[0x04+55]); 3257 outb(GDCIDX, 0x05); outb(GDCREG, modetable[0x05+55]); 3258 outb(GDCIDX, 0x06); outb(GDCREG, modetable[0x06+55]); 3259 if (crtc_addr == MONO_BASE) { 3260 outb(GDCIDX, 0x06); outb(GDCREG,(modetable[0x06+55] & 0x03) | 0x08); 3261 } 3262 else { 3263 outb(GDCIDX, 0x06); outb(GDCREG,(modetable[0x06+55] & 0x03) | 0x0c); 3264 } 3265#else 3266 outw(TSIDX, 0x0002 | (modetable[0x02+4]<<8)); 3267 outw(TSIDX, 0x0004 | (modetable[0x04+4]<<8)); 3268 outw(GDCIDX, 0x0004 | (modetable[0x04+55]<<8)); 3269 outw(GDCIDX, 0x0005 | (modetable[0x05+55]<<8)); 3270 if (crtc_addr == MONO_BASE) 3271 outw(GDCIDX, 0x0006 | (((modetable[0x06+55] & 0x03) | 0x08)<<8)); 3272 else 3273 outw(GDCIDX, 0x0006 | (((modetable[0x06+55] & 0x03) | 0x0c)<<8)); 3274#endif 3275 splx(s); 3276} 3277 3278void 3279copy_font(int operation, int font_type, char* font_image) 3280{ 3281 int ch, line, segment, fontsize; 3282 u_char val; 3283 3284 /* dont mess with console we dont know video mode on */ 3285 if (cur_console->status & UNKNOWN_MODE) 3286 return; 3287 3288 switch (font_type) { 3289 default: 3290 case FONT_8: 3291 segment = 0x8000; 3292 fontsize = 8; 3293 break; 3294 case FONT_14: 3295 segment = 0x4000; 3296 fontsize = 14; 3297 break; 3298 case FONT_16: 3299 segment = 0x0000; 3300 fontsize = 16; 3301 break; 3302 } 3303 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 3304 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 3305 set_font_mode(); 3306 for (ch=0; ch < 256; ch++) 3307 for (line=0; line < fontsize; line++) 3308 if (operation) 3309 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) = 3310 font_image[(ch*fontsize)+line]; 3311 else 3312 font_image[(ch*fontsize)+line] = 3313 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line); 3314 set_normal_mode(); 3315 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ 3316} 3317 3318static void 3319set_destructive_cursor(scr_stat *scp) 3320{ 3321 u_char cursor[32]; 3322 caddr_t address; 3323 int i; 3324 char *font_buffer; 3325 3326 3327 if (scp->font_size < FONT_14) { 3328 font_buffer = font_8; 3329 address = (caddr_t)VIDEOMEM + 0x8000; 3330 } 3331 else if (scp->font_size >= FONT_16) { 3332 font_buffer = font_16; 3333 address = (caddr_t)VIDEOMEM; 3334 } 3335 else { 3336 font_buffer = font_14; 3337 address = (caddr_t)VIDEOMEM + 0x4000; 3338 } 3339 3340 if (scp->status & MOUSE_VISIBLE) { 3341 if ((scp->cursor_saveunder & 0xff) == 0xd0) 3342 bcopyw(&scp->mouse_cursor[0], cursor, scp->font_size); 3343 else if ((scp->cursor_saveunder & 0xff) == 0xd1) 3344 bcopyw(&scp->mouse_cursor[32], cursor, scp->font_size); 3345 else if ((scp->cursor_saveunder & 0xff) == 0xd2) 3346 bcopyw(&scp->mouse_cursor[64], cursor, scp->font_size); 3347 else if ((scp->cursor_saveunder & 0xff) == 0xd3) 3348 bcopyw(&scp->mouse_cursor[96], cursor, scp->font_size); 3349 else 3350 bcopyw(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 3351 cursor, scp->font_size); 3352 } 3353 else 3354 bcopyw(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 3355 cursor, scp->font_size); 3356 for (i=0; i<32; i++) 3357 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 3358 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 3359 cursor[i] |= 0xff; 3360 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 3361 set_font_mode(); 3362 bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); 3363 set_normal_mode(); 3364} 3365 3366static void 3367set_mouse_pos(scr_stat *scp) 3368{ 3369 static int last_xpos = -1, last_ypos = -1; 3370 /* 3371 * the margins imposed here are not ideal, we loose 3372 * a couble of pixels on the borders.. 3373 */ 3374 if (scp->mouse_xpos < 0) 3375 scp->mouse_xpos = 0; 3376 if (scp->mouse_ypos < 0) 3377 scp->mouse_ypos = 0; 3378 if (scp->mouse_xpos > (scp->xsize*8)-2) 3379 scp->mouse_xpos = (scp->xsize*8)-2; 3380 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-2) 3381 scp->mouse_ypos = (scp->ysize*scp->font_size)-2; 3382 3383 if (scp->status & UNKNOWN_MODE) 3384 return; 3385 3386 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 3387 scp->status |= MOUSE_MOVED; 3388 3389 scp->mouse_pos = scp->scr_buf + 3390 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 3391 3392 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) { 3393 u_short *ptr; 3394 int i = 0; 3395 3396 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 3397 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 3398 scp->mouse_cut_end = scp->mouse_pos; 3399 for (ptr = (scp->mouse_cut_start > scp->mouse_cut_end 3400 ? scp->mouse_cut_end : scp->mouse_cut_start); 3401 ptr <= (scp->mouse_cut_start > scp->mouse_cut_end 3402 ? scp->mouse_cut_start : scp->mouse_cut_end); 3403 ptr++) { 3404 cut_buffer[i++] = *ptr & 0xff; 3405 if (((ptr - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 3406 cut_buffer[i++] = '\n'; 3407 } 3408 } 3409 cut_buffer[i] = 0x00; 3410 } 3411 } 3412} 3413 3414static void 3415mouse_cut_start(scr_stat *scp) 3416{ 3417 int i; 3418 3419 if (scp->status & MOUSE_VISIBLE) { 3420 if (scp->mouse_pos == scp->mouse_cut_start && 3421 scp->mouse_cut_start == scp->mouse_cut_end) { 3422 cut_buffer[0] = 0x00; 3423 remove_cutmarking(scp); 3424 } 3425 else { 3426 scp->mouse_cut_start = scp->mouse_cut_end = scp->mouse_pos; 3427 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 3428 cut_buffer[1] = 0x00; 3429 scp->status |= MOUSE_CUTTING; 3430 } 3431 mark_all(scp); 3432 /* delete all other screens cut markings */ 3433 for (i=0; i<MAXCONS; i++) { 3434 if (console[i] == NULL || console[i] == scp) 3435 continue; 3436 remove_cutmarking(console[i]); 3437 } 3438 } 3439} 3440 3441static void 3442mouse_cut_end(scr_stat *scp) 3443{ 3444 if (scp->status & MOUSE_VISIBLE) { 3445 scp->status &= ~MOUSE_CUTTING; 3446 } 3447} 3448 3449static void 3450mouse_paste(scr_stat *scp) 3451{ 3452 if (scp->status & MOUSE_VISIBLE) { 3453 struct tty *tp; 3454 u_char *ptr = cut_buffer; 3455 3456 tp = VIRTUAL_TTY(get_scr_num()); 3457 while (*ptr) 3458 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 3459 } 3460} 3461 3462static void 3463draw_mouse_image(scr_stat *scp) 3464{ 3465 caddr_t address; 3466 int i; 3467 char *font_buffer; 3468 u_short buffer[32]; 3469 u_short xoffset, yoffset; 3470 u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf); 3471 int font_size = scp->font_size; 3472 3473 if (font_size < FONT_14) { 3474 font_buffer = font_8; 3475 address = (caddr_t)VIDEOMEM + 0x8000; 3476 } 3477 else if (font_size >= FONT_16) { 3478 font_buffer = font_16; 3479 address = (caddr_t)VIDEOMEM; 3480 } 3481 else { 3482 font_buffer = font_14; 3483 address = (caddr_t)VIDEOMEM + 0x4000; 3484 } 3485 xoffset = scp->mouse_xpos % 8; 3486 yoffset = scp->mouse_ypos % font_size; 3487 3488 /* prepare mousepointer char's bitmaps */ 3489 bcopyw(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 3490 &scp->mouse_cursor[0], font_size); 3491 bcopyw(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 3492 &scp->mouse_cursor[32], font_size); 3493 bcopyw(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 3494 &scp->mouse_cursor[64], font_size); 3495 bcopyw(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 3496 &scp->mouse_cursor[96], font_size); 3497 for (i=0; i<font_size; i++) { 3498 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 3499 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 3500 } 3501 3502 /* now and-or in the mousepointer image */ 3503 for (i=0; i<16; i++) { 3504 buffer[i+yoffset] = 3505 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 3506 | (mouse_or_mask[i] >> xoffset); 3507 } 3508 for (i=0; i<font_size; i++) { 3509 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 3510 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 3511 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 3512 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 3513 } 3514 3515 scp->mouse_oldpos = scp->mouse_pos; 3516 3517 /* wait for vertical retrace to avoid jitter on some videocards */ 3518 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 3519 set_font_mode(); 3520 bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); 3521 set_normal_mode(); 3522 *(crt_pos) = (*(scp->mouse_pos)&0xff00)|0xd0; 3523 *(crt_pos+scp->xsize) = (*(scp->mouse_pos+scp->xsize)&0xff00)|0xd2; 3524 if (scp->mouse_xpos < (scp->xsize-1)*8) { 3525 *(crt_pos+1) = (*(scp->mouse_pos+1)&0xff00)|0xd1; 3526 *(crt_pos+scp->xsize+1) = (*(scp->mouse_pos+scp->xsize+1)&0xff00)|0xd3; 3527 } 3528 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 3529 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 3530} 3531 3532static void 3533remove_mouse_image(scr_stat *scp) 3534{ 3535 u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf); 3536 3537 *(crt_pos) = *(scp->mouse_oldpos); 3538 *(crt_pos+1) = *(scp->mouse_oldpos+1); 3539 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 3540 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 3541 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 3542 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 3543} 3544 3545static void 3546draw_cutmarking(scr_stat *scp) 3547{ 3548 u_short *ptr; 3549 u_short och, nch; 3550 3551 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 3552 nch = och = *(Crtat + (ptr - scp->scr_buf)); 3553 /* are we outside the selected area ? */ 3554 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 3555 scp->mouse_cut_end : scp->mouse_cut_start) || 3556 ptr > (scp->mouse_cut_start > scp->mouse_cut_end ? 3557 scp->mouse_cut_start : scp->mouse_cut_end)) { 3558 if (ptr != scp->cursor_pos) 3559 nch = (och & 0xff) | (*ptr & 0xff00); 3560 } 3561 else { 3562 /* are we clear of the cursor image ? */ 3563 if (ptr != scp->cursor_pos) 3564 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 3565 else { 3566 if (flags & CHAR_CURSOR) 3567 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 3568 else 3569 if (!(flags & BLINK_CURSOR)) 3570 nch = (och & 0xff) | (*ptr & 0xff00); 3571 } 3572 } 3573 if (nch != och) 3574 *(Crtat + (ptr - scp->scr_buf)) = nch; 3575 } 3576} 3577 3578static void 3579remove_cutmarking(scr_stat *scp) 3580{ 3581 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3582 scp->status &= ~MOUSE_CUTTING; 3583 mark_all(scp); 3584} 3585 3586static void 3587save_palette(void) 3588{ 3589 int i; 3590 3591 outb(PALRADR, 0x00); 3592 for (i=0x00; i<0x300; i++) 3593 palette[i] = inb(PALDATA); 3594 inb(crtc_addr+6); /* reset flip/flop */ 3595} 3596 3597void 3598load_palette(void) 3599{ 3600 int i; 3601 3602 outb(PIXMASK, 0xFF); /* no pixelmask */ 3603 outb(PALWADR, 0x00); 3604 for (i=0x00; i<0x300; i++) 3605 outb(PALDATA, palette[i]); 3606 inb(crtc_addr+6); /* reset flip/flop */ 3607 outb(ATC, 0x20); /* enable palette */ 3608} 3609 3610static void 3611do_bell(scr_stat *scp, int pitch, int duration) 3612{ 3613 if (flags & VISUAL_BELL) { 3614 if (blink_in_progress) 3615 return; 3616 blink_in_progress = 4; 3617 if (scp != cur_console) 3618 blink_in_progress += 2; 3619 blink_screen(cur_console); 3620 timeout((timeout_func_t)blink_screen, cur_console, hz/10); 3621 } else { 3622 if (scp != cur_console) 3623 pitch *= 2; 3624 sysbeep(pitch, duration); 3625 } 3626} 3627 3628static void 3629blink_screen(scr_stat *scp) 3630{ 3631 if (blink_in_progress > 1) { 3632 if (blink_in_progress & 1) 3633 fillw(kernel_default.std_color | scr_map[0x20], 3634 Crtat, scp->xsize * scp->ysize); 3635 else 3636 fillw(kernel_default.rev_color | scr_map[0x20], 3637 Crtat, scp->xsize * scp->ysize); 3638 blink_in_progress--; 3639 timeout((timeout_func_t)blink_screen, scp, hz/10); 3640 } 3641 else { 3642 blink_in_progress = FALSE; 3643 mark_all(scp); 3644 if (delayed_next_scr) 3645 switch_scr(scp, delayed_next_scr - 1); 3646 } 3647} 3648 3649#ifdef SC_SPLASH_SCREEN 3650static void 3651toggle_splash_screen(scr_stat *scp) 3652{ 3653 static int toggle = 0; 3654 static u_char save_mode; 3655 int s = splhigh(); 3656 3657 if (toggle) { 3658 scp->mode = save_mode; 3659 scp->status &= ~UNKNOWN_MODE; 3660 set_mode(scp); 3661 toggle = 0; 3662 } 3663 else { 3664 save_mode = scp->mode; 3665 scp->mode = M_VGA_CG320; 3666 scp->status |= UNKNOWN_MODE; 3667 set_mode(scp); 3668 /* load image */ 3669 toggle = 1; 3670 } 3671 splx(s); 3672} 3673#endif 3674#endif /* NSC */ 3675