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