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