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