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