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