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