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