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