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