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