syscons.c revision 1071
1/*- 2 * Copyright (c) 1992-1994 S�ren Schmidt 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz and Don Ahn. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from:@(#)syscons.c 1.3 940129 38 * $Id: syscons.c,v 1.31 1994/02/01 15:09:10 rich Exp $ 39 * 40 */ 41 42#if !defined(FADE_SAVER) && !defined(BLANK_SAVER) && !defined(STAR_SAVER) && !defined(SNAKE_SAVER) 43#define SNAKE_SAVER 44#endif 45 46#if !defined(__FreeBSD__) 47#define FAT_CURSOR 48#endif 49 50#include "param.h" 51#include "conf.h" 52#include "ioctl.h" 53#include "proc.h" 54#include "user.h" 55#include "tty.h" 56#include "uio.h" 57#include "callout.h" 58#include "systm.h" 59#include "kernel.h" 60#include "syslog.h" 61#include "errno.h" 62#include "malloc.h" 63#include "i386/isa/isa.h" 64#include "i386/isa/isa_device.h" 65#include "i386/isa/timerreg.h" 66#include "i386/i386/cons.h" 67#include "machine/console.h" 68#include "machine/psl.h" 69#include "machine/frame.h" 70#include "machine/pc/display.h" 71#include "iso8859.font" 72#include "kbdtables.h" 73#include "sc.h" 74 75#if NSC > 0 76 77#if !defined(NCONS) 78#define NCONS 12 79#endif 80 81/* status flags */ 82#define LOCK_KEY_MASK 0x0000F 83#define LED_MASK 0x00007 84#define UNKNOWN_MODE 0x00010 85#define KBD_RAW_MODE 0x00020 86#define SWITCH_WAIT_REL 0x00040 87#define SWITCH_WAIT_ACQ 0x00080 88 89/* video hardware memory addresses */ 90#define VIDEOMEM 0x000A0000 91 92/* misc defines */ 93#define MAX_ESC_PAR 3 94#define TEXT80x25 1 95#define TEXT80x50 2 96#define COL 80 97#define ROW 25 98#define BELL_DURATION 5 99#define BELL_PITCH 800 100#define TIMER_FREQ 1193182 /* should be in isa.h */ 101#define PCBURST 128 102 103/* defines related to hardware addresses */ 104#define MONO_BASE 0x3B4 /* crt controller base mono */ 105#define COLOR_BASE 0x3D4 /* crt controller base color */ 106#define ATC IO_VGA+0x00 /* attribute controller */ 107#define TSIDX IO_VGA+0x04 /* timing sequencer idx */ 108#define TSREG IO_VGA+0x05 /* timing sequencer data */ 109#define PIXMASK IO_VGA+0x06 /* pixel write mask */ 110#define PALRADR IO_VGA+0x07 /* palette read address */ 111#define PALWADR IO_VGA+0x08 /* palette write address */ 112#define PALDATA IO_VGA+0x09 /* palette data register */ 113#define GDCIDX IO_VGA+0x0E /* graph data controller idx */ 114#define GDCREG IO_VGA+0x0F /* graph data controller data */ 115 116/* special characters */ 117#define cntlc 0x03 118#define cntld 0x04 119#define bs 0x08 120#define lf 0x0a 121#define cr 0x0d 122#define del 0x7f 123 124typedef struct term_stat { 125 int esc; /* processing escape sequence */ 126 int num_param; /* # of parameters to ESC */ 127 int last_param; /* last parameter # */ 128 int param[MAX_ESC_PAR]; /* contains ESC parameters */ 129 int cur_attr; /* current attributes */ 130 int std_attr; /* normal attributes */ 131 int rev_attr; /* reverse attributes */ 132} term_stat; 133 134typedef struct scr_stat { 135 u_short *crt_base; /* address of screen memory */ 136 u_short *scr_buf; /* buffer when off screen */ 137 u_short *crtat; /* cursor address */ 138 int xpos; /* current X position */ 139 int ypos; /* current Y position */ 140 int xsize; /* X size */ 141 int ysize; /* Y size */ 142 term_stat term; /* terminal emulation stuff */ 143 char cursor_start; /* cursor start line # */ 144 char cursor_end; /* cursor end line # */ 145 u_char border; /* border color */ 146 u_short bell_duration; 147 u_short bell_pitch; 148 u_short status; /* status (bitfield) */ 149 u_short mode; /* mode */ 150 pid_t pid; /* pid of controlling proc */ 151 struct proc *proc; /* proc* of controlling proc */ 152 struct vt_mode smode; /* switch mode */ 153} scr_stat; 154 155typedef struct default_attr { 156 int std_attr; /* normal attributes */ 157 int rev_attr; /* reverse attributes */ 158} default_attr; 159 160static default_attr user_default = { 161 (FG_LIGHTGREY | BG_BLACK) << 8, 162 (FG_BLACK | BG_LIGHTGREY) << 8 163}; 164 165static default_attr kernel_default = { 166 (FG_WHITE | BG_BLACK) << 8, 167 (FG_BLACK | BG_LIGHTGREY) << 8 168}; 169 170static scr_stat console[NCONS]; 171static scr_stat *cur_console = &console[0]; 172static scr_stat *new_scp, *old_scp; 173static term_stat kernel_console; 174static default_attr *current_default; 175static int switch_in_progress = 0; 176static u_short *crtat = 0; 177static u_int crtc_addr = MONO_BASE; 178static char crtc_vga = 0; 179static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 180static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 181static char palette[3*256]; 182static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 183static int cur_cursor_pos = -1; 184static char in_putc = 0; 185static char polling = 0; 186static int delayed_next_scr; 187static char saved_console = -1; /* saved console number */ 188static long scrn_blank_time = 0; /* screen saver timout value */ 189static int scrn_blanked = 0; /* screen saver active flag */ 190static long scrn_time_stamp; 191static u_char scr_map[256]; 192extern int hz; 193extern struct timeval time; 194 195/* function prototypes */ 196int pcprobe(struct isa_device *dev); 197int pcattach(struct isa_device *dev); 198int pcopen(dev_t dev, int flag, int mode, struct proc *p); 199int pcclose(dev_t dev, int flag, int mode, struct proc *p); 200int pcread(dev_t dev, struct uio *uio, int flag); 201int pcwrite(dev_t dev, struct uio *uio, int flag); 202int pcparam(struct tty *tp, struct termios *t); 203int pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p); 204void pcxint(dev_t dev); 205void pcstart(struct tty *tp); 206void pccnprobe(struct consdev *cp); 207void pccninit(struct consdev *cp); 208void pccnputc(dev_t dev, char c); 209int pccngetc(dev_t dev); 210void scintr(int unit); 211int pcmmap(dev_t dev, int offset, int nprot); 212u_int sgetc(int noblock); 213int getchar(void); 214static void scinit(void); 215static void scput(u_char c); 216static u_int scgetc(int noblock); 217static void scrn_saver(int test); 218static struct tty *get_tty_ptr(dev_t dev); 219static scr_stat *get_scr_stat(dev_t dev); 220static int get_scr_num(); 221static void cursor_shape(int start, int end); 222static void get_cursor_shape(int *start, int *end); 223static void cursor_pos(int force); 224static void clear_screen(scr_stat *scp); 225static int switch_scr(u_int next_scr); 226static void exchange_scr(void); 227static void move_crsr(scr_stat *scp, int x, int y); 228static void move_up(u_short *s, u_short *d, u_int len); 229static void move_down(u_short *s, u_short *d, u_int len); 230static void scan_esc(scr_stat *scp, u_char c); 231static void ansi_put(scr_stat *scp, u_char c); 232static u_char *get_fstr(u_int c, u_int *len); 233static void update_leds(int which); 234static void kbd_wait(void); 235static void kbd_cmd(u_char command); 236static void kbd_cmd2(u_char command, u_char arg); 237static int kbd_reply(void); 238static void set_mode(scr_stat *scp); 239static void set_border(int color); 240static void load_font(int segment, int size, char* font); 241static void save_palette(void); 242static void load_palette(void); 243static void change_winsize(struct tty *tp, int x, int y); 244 245 246/* OS specific stuff */ 247 248#if defined(NetBSD) 249#define VIRTUAL_TTY(x) pc_tty[x] ? (pc_tty[x]) : (pc_tty[x] = ttymalloc()) 250#define CONSOLE_TTY pc_tty[NCONS] ? (pc_tty[NCONS]) : (pc_tty[NCONS] = ttymalloc()) 251#define frametype struct trapframe 252#define eflags tf_eflags 253extern u_short *Crtat; 254struct tty *pc_tty[NCONS+1]; 255int ttrstrt(); 256#endif 257 258#if defined(__FreeBSD__) 259#define frametype struct trapframe 260#define eflags tf_eflags 261#define timeout_t timeout_func_t 262#define MONO_BUF (KERNBASE+0xB0000) 263#define CGA_BUF (KERNBASE+0xB8000) 264#endif 265 266#if defined(__386BSD__) && !defined(__FreeBSD__) 267#define frametype struct syscframe 268#define eflags sf_eflags 269#define timeout_t caddr_t 270#define MONO_BUF (0xFE0B0000) 271#define CGA_BUF (0xFE0B8000) 272#endif 273 274#if defined(__386BSD__) || defined(__FreeBSD__) 275#define VIRTUAL_TTY(x) &pccons[x] 276#define CONSOLE_TTY &pccons[NCONS] 277u_short *Crtat = (u_short *)MONO_BUF; 278struct tty pccons[NCONS+1]; 279void consinit(void) {scinit();} 280#include "ddb.h" 281#if NDDB > 0 282#define DDB 1 283#endif 284#endif 285 286 287struct isa_driver scdriver = { 288 pcprobe, pcattach, "sc", 289}; 290 291 292int pcprobe(struct isa_device *dev) 293{ 294 /* Enable interrupts and keyboard controller */ 295 kbd_wait(); 296 outb(KB_STAT, KB_WRITE); 297 kbd_cmd(0x4D); 298 299 /* Start keyboard stuff RESET */ 300 for (;;) { 301 kbd_cmd(KB_RESET); 302 if (kbd_reply() == KB_ACK && /* command accepted */ 303 kbd_reply() == 0xaa) /* self test passed */ 304 break; 305 printf("Keyboard reset failed\n"); 306 } 307 return (IO_KBDSIZE); 308} 309 310 311int pcattach(struct isa_device *dev) 312{ 313 scr_stat *scp; 314 int start = -1, end = -1, i; 315 316 printf("sc%d: ", dev->id_unit); 317 if (crtc_vga) 318 if (crtc_addr == MONO_BASE) 319 printf("VGA mono"); 320 else 321 printf("VGA color"); 322 else 323 if (crtc_addr == MONO_BASE) 324 printf("MDA/hercules"); 325 else 326 printf("CGA/EGA"); 327 328 if (NCONS > 1) 329 printf(" <%d virtual consoles>\n", NCONS); 330 else 331 printf("\n"); 332#if defined(FAT_CURSOR) 333 start = 0; 334 end = 18; 335 if (crtc_vga) { 336#else 337 if (crtc_vga) { 338 get_cursor_shape(&start, &end); 339#endif 340 save_palette(); 341 load_font(0, 16, font_8x16); 342 load_font(1, 8, font_8x8); 343 load_font(2, 14, font_8x14); 344 } 345 current_default = &user_default; 346 for (i = 0; i < NCONS; i++) { 347 scp = &console[i]; 348 scp->scr_buf = (u_short *)malloc(COL * ROW * 2, M_DEVBUF, M_NOWAIT); 349 scp->mode = TEXT80x25; 350 scp->term.esc = 0; 351 scp->term.std_attr = current_default->std_attr; 352 scp->term.rev_attr = current_default->rev_attr; 353 scp->term.cur_attr = scp->term.std_attr; 354 scp->border = BG_BLACK; 355 scp->cursor_start = start; 356 scp->cursor_end = end; 357 scp->xsize = COL; 358 scp->ysize = ROW; 359 scp->bell_pitch = BELL_PITCH; 360 scp->bell_duration = BELL_DURATION; 361 scp->status = 0; 362 scp->pid = 0; 363 scp->proc = NULL; 364 scp->smode.mode = VT_AUTO; 365 if (i > 0) { 366 scp->crt_base = scp->crtat = scp->scr_buf; 367 fillw(scp->term.cur_attr|scr_map[0x20], scp->scr_buf, COL*ROW); 368 } 369 } 370 /* get cursor going */ 371#if defined(FAT_CURSOR) 372 cursor_shape(console[0].cursor_start, 373 console[0].cursor_end); 374#endif 375 cursor_pos(1); 376 return 0; 377} 378 379 380static struct tty *get_tty_ptr(dev_t dev) 381{ 382 int unit = minor(dev); 383 384 if (unit > NCONS) 385 return(NULL); 386 if (unit == NCONS) 387 return(CONSOLE_TTY); 388 return(VIRTUAL_TTY(unit)); 389} 390 391 392static scr_stat *get_scr_stat(dev_t dev) 393{ 394 int unit = minor(dev); 395 396 if (unit > NCONS) 397 return(NULL); 398 if (unit == NCONS) 399 return(&console[0]); 400 return(&console[unit]); 401} 402 403 404static int get_scr_num() 405{ 406 int i = 0; 407 408 while ((i < NCONS) && (cur_console != &console[i])) i++; 409 return i < NCONS ? i : 0; 410} 411 412int pcopen(dev_t dev, int flag, int mode, struct proc *p) 413{ 414 struct tty *tp = get_tty_ptr(dev); 415 416 if (!tp) 417 return(ENXIO); 418 419 tp->t_oproc = pcstart; 420 tp->t_param = pcparam; 421 tp->t_dev = dev; 422 if (!(tp->t_state & TS_ISOPEN)) { 423 tp->t_state |= TS_WOPEN; 424 ttychars(tp); 425 tp->t_iflag = TTYDEF_IFLAG; 426 tp->t_oflag = TTYDEF_OFLAG; 427 tp->t_cflag = TTYDEF_CFLAG; 428 tp->t_lflag = TTYDEF_LFLAG; 429 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 430 pcparam(tp, &tp->t_termios); 431 ttsetwater(tp); 432 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 433 return(EBUSY); 434 tp->t_state |= TS_CARR_ON; 435 tp->t_cflag |= CLOCAL; 436#if defined(__FreeBSD__) 437 return((*linesw[tp->t_line].l_open)(dev, tp, 0)); 438#else 439 return((*linesw[tp->t_line].l_open)(dev, tp)); 440#endif 441} 442 443 444int pcclose(dev_t dev, int flag, int mode, struct proc *p) 445{ 446 struct tty *tp = get_tty_ptr(dev); 447 struct scr_stat *scp; 448 449 if (!tp) 450 return(ENXIO); 451 if (minor(dev) < NCONS) { 452 scp = get_scr_stat(tp->t_dev); 453 if (scp->status & SWITCH_WAIT_ACQ) 454 wakeup((caddr_t)&scp->smode); 455 scp->pid = 0; 456 scp->proc = NULL; 457 scp->smode.mode = VT_AUTO; 458 } 459 (*linesw[tp->t_line].l_close)(tp, flag); 460 ttyclose(tp); 461 return(0); 462} 463 464 465int pcread(dev_t dev, struct uio *uio, int flag) 466{ 467 struct tty *tp = get_tty_ptr(dev); 468 469 if (!tp) 470 return(ENXIO); 471 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 472} 473 474 475int pcwrite(dev_t dev, struct uio *uio, int flag) 476{ 477 struct tty *tp = get_tty_ptr(dev); 478 479 if (!tp) 480 return(ENXIO); 481 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 482} 483 484 485/* 486 * Got a console interrupt, keyboard action ! 487 * Catch the character, and see who it goes to. 488 */ 489void scintr(int unit) 490{ 491 static struct tty *cur_tty; 492 int c, len; 493 u_char *cp; 494 495 /* make screensaver happy */ 496 scrn_time_stamp = time.tv_sec; 497 if (scrn_blanked) 498 scrn_saver(0); 499 500 c = scgetc(1); 501 502 cur_tty = VIRTUAL_TTY(get_scr_num()); 503 if (!(cur_tty->t_state & TS_ISOPEN)) 504 cur_tty = CONSOLE_TTY; 505 506 if (!(cur_tty->t_state & TS_ISOPEN) || polling) 507 return; 508 509 switch (c & 0xff00) { 510 case 0x0000: /* normal key */ 511 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 512 break; 513 case NOKEY: /* nothing there */ 514 break; 515 case FKEY: /* function key, return string */ 516 if (cp = get_fstr((u_int)c, (u_int *)&len)) { 517 while (len-- > 0) 518 (*linesw[cur_tty->t_line].l_rint) 519 (*cp++ & 0xFF, cur_tty); 520 } 521 break; 522 case MKEY: /* meta is active, prepend ESC */ 523 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 524 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 525 break; 526 } 527} 528 529 530/* 531 * Set line parameters 532 */ 533int pcparam(struct tty *tp, struct termios *t) 534{ 535 int cflag = t->c_cflag; 536 537 /* and copy to tty */ 538 tp->t_ispeed = t->c_ispeed; 539 tp->t_ospeed = t->c_ospeed; 540 tp->t_cflag = cflag; 541 return 0; 542} 543 544 545int pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 546{ 547 int i, error; 548 struct tty *tp; 549 frametype *fp; 550 scr_stat *scp; 551 552 tp = get_tty_ptr(dev); 553 if (!tp) 554 return ENXIO; 555 scp = get_scr_stat(tp->t_dev); 556 557 switch (cmd) { /* process console hardware related ioctl's */ 558 559 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 560 scrn_blank_time = *(int*)data; 561 return 0; 562 563 case CONS_80x25TEXT: /* set 80x25 text mode */ 564 if (!crtc_vga) 565 return ENXIO; 566 scp->mode = TEXT80x25; 567 scp->ysize = 25; 568 free(scp->scr_buf, M_DEVBUF); 569 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*2, 570 M_DEVBUF, M_NOWAIT); 571 if (scp != cur_console) 572 scp->crt_base = scp->scr_buf; 573 set_mode(scp); 574 clear_screen(scp); 575 change_winsize(tp, scp->xsize, scp->ysize); 576 return 0; 577 578 case CONS_80x50TEXT: /* set 80x50 text mode */ 579 if (!crtc_vga) 580 return ENXIO; 581 scp->mode = TEXT80x50; 582 scp->ysize = 50; 583 free(scp->scr_buf, M_DEVBUF); 584 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*2, 585 M_DEVBUF, M_NOWAIT); 586 if (scp != cur_console) 587 scp->crt_base = scp->scr_buf; 588 set_mode(scp); 589 clear_screen(scp); 590 change_winsize(tp, scp->xsize, scp->ysize); 591 return 0; 592 593 case CONS_GETVERS: /* get version number */ 594 *(int*)data = 0x103; /* version 1.3 */ 595 return 0; 596 597 case CONS_GETINFO: /* get current (virtual) console info */ 598 if (*data == sizeof(struct vid_info)) { 599 vid_info_t *ptr = (vid_info_t*)data; 600 ptr->m_num = get_scr_num(); 601 ptr->mv_col = scp->xpos; 602 ptr->mv_row = scp->ypos; 603 ptr->mv_csz = scp->xsize; 604 ptr->mv_rsz = scp->ysize; 605 ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8; 606 ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12; 607 ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8; 608 ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12; 609 ptr->mv_grfc.fore = 0; /* not supported */ 610 ptr->mv_grfc.back = 0; /* not supported */ 611 ptr->mv_ovscan = scp->border; 612 ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 613 return 0; 614 } 615 return EINVAL; 616 617 case VT_SETMODE: /* set screen switcher mode */ 618 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 619 if (scp->smode.mode == VT_PROCESS) { 620 scp->proc = p; 621 scp->pid = scp->proc->p_pid; 622 } 623 return 0; 624 625 case VT_GETMODE: /* get screen switcher mode */ 626 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 627 return 0; 628 629 case VT_RELDISP: /* screen switcher ioctl */ 630 switch(*data) { 631 case VT_FALSE: /* user refuses to release screen, abort */ 632 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 633 old_scp->status &= ~SWITCH_WAIT_REL; 634 switch_in_progress = 0; 635 return 0; 636 } 637 return EINVAL; 638 639 case VT_TRUE: /* user has released screen, go on */ 640 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 641 scp->status &= ~SWITCH_WAIT_REL; 642 exchange_scr(); 643 if (new_scp->smode.mode == VT_PROCESS) { 644 new_scp->status |= SWITCH_WAIT_ACQ; 645 psignal(new_scp->proc, 646 new_scp->smode.acqsig); 647 } 648 else 649 switch_in_progress = 0; 650 return 0; 651 } 652 return EINVAL; 653 654 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 655 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 656 scp->status &= ~SWITCH_WAIT_ACQ; 657 switch_in_progress = 0; 658 return 0; 659 } 660 return EINVAL; 661 662 default: 663 return EINVAL; 664 } 665 /* NOT REACHED */ 666 667 case VT_OPENQRY: /* return free virtual console */ 668 for (i = 0; i < NCONS; i++) { 669 tp = VIRTUAL_TTY(i); 670 if (!(tp->t_state & TS_ISOPEN)) { 671 *data = i + 1; 672 return 0; 673 } 674 } 675 return EINVAL; 676 677 case VT_ACTIVATE: /* switch to screen *data */ 678 return switch_scr((*data) - 1); 679 680 case VT_WAITACTIVE: /* wait for switch to occur */ 681 if (*data > NCONS) 682 return EINVAL; 683 if (minor(dev) == (*data) - 1) 684 return 0; 685 if (*data == 0) { 686 if (scp == cur_console) 687 return 0; 688 while ((error=tsleep((caddr_t)&scp->smode, 689 PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; 690 } 691 else 692 while ((error=tsleep( 693 (caddr_t)&console[*(data-1)].smode, 694 PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; 695 return error; 696 697 case VT_GETACTIVE: 698 *data = get_scr_num()+1; 699 return 0; 700 701 case KDENABIO: /* allow io operations */ 702 fp = (frametype *)p->p_regs; 703 fp->eflags |= PSL_IOPL; 704 return 0; 705 706 case KDDISABIO: /* disallow io operations (default) */ 707 fp = (frametype *)p->p_regs; 708 fp->eflags &= ~PSL_IOPL; 709 return 0; 710 711 case KDSETMODE: /* set current mode of this (virtual) console */ 712 switch (*data) { 713 case KD_TEXT: /* switch to TEXT (known) mode */ 714 /* restore fonts & palette ! */ 715 if (crtc_vga) { 716 load_font(0, 16, font_8x16); 717 load_font(1, 8, font_8x8); 718 load_font(2, 14, font_8x14); 719 load_palette(); 720 } 721 /* FALL THROUGH */ 722 723 case KD_TEXT1: /* switch to TEXT (known) mode */ 724 /* no restore fonts & palette */ 725 scp->status &= ~UNKNOWN_MODE; 726 set_mode(scp); 727 clear_screen(scp); 728 return 0; 729 730 case KD_GRAPHICS:/* switch to GRAPHICS (unknown) mode */ 731 scp->status |= UNKNOWN_MODE; 732 return 0; 733 default: 734 return EINVAL; 735 } 736 /* NOT REACHED */ 737 738 case KDGETMODE: /* get current mode of this (virtual) console */ 739 *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 740 return 0; 741 742 case KDSBORDER: /* set border color of this (virtual) console */ 743 if (!crtc_vga) 744 return ENXIO; 745 scp->border = *data; 746 if (scp == cur_console) 747 set_border(scp->border); 748 return 0; 749 750 case KDSKBSTATE: /* set keyboard state (locks) */ 751 if (*data >= 0 && *data <= LOCK_KEY_MASK) { 752 scp->status &= ~LOCK_KEY_MASK; 753 scp->status |= *data; 754 if (scp == cur_console) 755 update_leds(scp->status & LED_MASK); 756 return 0; 757 } 758 return EINVAL; 759 760 case KDGKBSTATE: /* get keyboard state (locks) */ 761 *data = scp->status & LOCK_KEY_MASK; 762 return 0; 763 764 case KDSETRAD: /* set keyboard repeat & delay rates */ 765 if (*data & 0x80) 766 return EINVAL; 767 kbd_cmd2(KB_SETRAD, *data); 768 return 0; 769 770 case KDSKBMODE: /* set keyboard mode */ 771 switch (*data) { 772 case K_RAW: /* switch to RAW scancode mode */ 773 scp->status |= KBD_RAW_MODE; 774 return 0; 775 776 case K_XLATE: /* switch to XLT ascii mode */ 777 if (scp == cur_console && scp->status == KBD_RAW_MODE) 778 shfts = ctls = alts = agrs = metas = 0; 779 scp->status &= ~KBD_RAW_MODE; 780 return 0; 781 default: 782 return EINVAL; 783 } 784 /* NOT REACHED */ 785 786 case KDGKBMODE: /* get keyboard mode */ 787 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE; 788 return 0; 789 790 case KDMKTONE: /* sound the bell */ 791 if (scp == cur_console) 792 sysbeep(scp->bell_pitch, scp->bell_duration); 793 return 0; 794 795 case KIOCSOUND: /* make tone (*data) hz */ 796 if (scp == cur_console) { 797 if (*(int*)data) { 798 int pitch = TIMER_FREQ/(*(int*)data); 799 /* enable counter 2 */ 800 outb(0x61, inb(0x61) | 3); 801 /* set command for counter 2, 2 byte write */ 802 outb(TIMER_MODE, 803 TIMER_SEL2|TIMER_16BIT|TIMER_SQWAVE); 804 /* set pitch */ 805 outb(TIMER_CNTR2, pitch); 806 outb(TIMER_CNTR2, (pitch>>8)); 807 } 808 else { 809 /* disable counter 2 */ 810 outb(0x61, inb(0x61) & 0xFC); 811 } 812 } 813 return 0; 814 815 case KDGKBTYPE: /* get keyboard type */ 816 *data = 0; /* type not known (yet) */ 817 return 0; 818 819 case KDSETLED: /* set keyboard LED status */ 820 if (*data >= 0 && *data <= LED_MASK) { 821 scp->status &= ~LED_MASK; 822 scp->status |= *data; 823 if (scp == cur_console) 824 update_leds(scp->status & LED_MASK); 825 return 0; 826 } 827 return EINVAL; 828 829 case KDGETLED: /* get keyboard LED status */ 830 *data = scp->status & LED_MASK; 831 return 0; 832 833 case GETFKEY: /* get functionkey string */ 834 if (*(u_short*)data < n_fkey_tab) { 835 fkeyarg_t *ptr = (fkeyarg_t*)data; 836 bcopy(&fkey_tab[ptr->keynum].str, 837 ptr->keydef, 838 fkey_tab[ptr->keynum].len); 839 ptr->flen = fkey_tab[ptr->keynum].len; 840 return 0; 841 } 842 else 843 return EINVAL; 844 845 case SETFKEY: /* set functionkey string */ 846 if (*(u_short*)data < n_fkey_tab) { 847 fkeyarg_t *ptr = (fkeyarg_t*)data; 848 bcopy(ptr->keydef, 849 &fkey_tab[ptr->keynum].str, 850 min(ptr->flen, MAXFK)); 851 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 852 return 0; 853 } 854 else 855 return EINVAL; 856 857 case GIO_SCRNMAP: /* get output translation table */ 858 bcopy(&scr_map, data, sizeof(scr_map)); 859 return 0; 860 861 case PIO_SCRNMAP: /* set output translation table */ 862 bcopy(data, &scr_map, sizeof(scr_map)); 863 return 0; 864 865 case GIO_KEYMAP: /* get keyboard translation table */ 866 bcopy(&key_map, data, sizeof(key_map)); 867 return 0; 868 869 case PIO_KEYMAP: /* set keyboard translation table */ 870 bcopy(data, &key_map, sizeof(key_map)); 871 return 0; 872 873 case PIO_FONT8x8: /* set 8x8 dot font */ 874 if (!crtc_vga) 875 return ENXIO; 876 bcopy(data, &font_8x8, sizeof(font_8x8)); 877 load_font(1, 8, font_8x8); 878 return 0; 879 880 case GIO_FONT8x8: /* get 8x8 dot font */ 881 if (!crtc_vga) 882 return ENXIO; 883 bcopy(&font_8x8, data, sizeof(font_8x8)); 884 return 0; 885 886 case PIO_FONT8x14: /* set 8x14 dot font */ 887 if (!crtc_vga) 888 return ENXIO; 889 bcopy(data, &font_8x14, sizeof(font_8x14)); 890 load_font(2, 14, font_8x14); 891 return 0; 892 893 case GIO_FONT8x14: /* get 8x14 dot font */ 894 if (!crtc_vga) 895 return ENXIO; 896 bcopy(&font_8x14, data, sizeof(font_8x14)); 897 return 0; 898 899 case PIO_FONT8x16: /* set 8x16 dot font */ 900 if (!crtc_vga) 901 return ENXIO; 902 bcopy(data, &font_8x16, sizeof(font_8x16)); 903 load_font(0, 16, font_8x16); 904 return 0; 905 906 case GIO_FONT8x16: /* get 8x16 dot font */ 907 if (!crtc_vga) 908 return ENXIO; 909 bcopy(&font_8x16, data, sizeof(font_8x16)); 910 return 0; 911 912 case CONSOLE_X_MODE_ON: /* just to be compatible */ 913 if (saved_console < 0) { 914 saved_console = get_scr_num(); 915 switch_scr(minor(dev)); 916 fp = (frametype *)p->p_regs; 917 fp->eflags |= PSL_IOPL; 918 scp->status |= UNKNOWN_MODE; 919 scp->status |= KBD_RAW_MODE; 920 return 0; 921 } 922 return EAGAIN; 923 924 case CONSOLE_X_MODE_OFF:/* just to be compatible */ 925 fp = (frametype *)p->p_regs; 926 fp->eflags &= ~PSL_IOPL; 927 if (crtc_vga) { 928 load_font(0, 16, font_8x16); 929 load_font(1, 8, font_8x8); 930 load_font(2, 14, font_8x14); 931 load_palette(); 932 } 933 scp->status &= ~UNKNOWN_MODE; 934 set_mode(scp); 935 clear_screen(scp); 936 scp->status &= ~KBD_RAW_MODE; 937 switch_scr(saved_console); 938 saved_console = -1; 939 return 0; 940 941 case CONSOLE_X_BELL: /* more compatibility */ 942 /* 943 * if set, data is a pointer to a length 2 array of 944 * integers. data[0] is the pitch in Hz and data[1] 945 * is the duration in msec. 946 */ 947 if (data) 948 sysbeep(TIMER_FREQ/((int*)data)[0], 949 ((int*)data)[1]*hz/3000); 950 else 951 sysbeep(scp->bell_pitch, scp->bell_duration); 952 return 0; 953 954 default: 955 break; 956 } 957 958 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 959 if (error >= 0) 960 return(error); 961 error = ttioctl(tp, cmd, data, flag); 962 if (error >= 0) 963 return(error); 964 return(ENOTTY); 965} 966 967 968void pcxint(dev_t dev) 969{ 970 struct tty *tp = get_tty_ptr(dev); 971 972 if (!tp) 973 return; 974 tp->t_state &= ~TS_BUSY; 975 if (tp->t_line) 976 (*linesw[tp->t_line].l_start)(tp); 977 else 978 pcstart(tp); 979} 980 981 982void pcstart(struct tty *tp) 983{ 984#if defined(NetBSD) 985 struct clist *rbp; 986 int i, s, len; 987 u_char buf[PCBURST]; 988 scr_stat *scp = get_scr_stat(tp->t_dev); 989 990 if (scp->status & SLKED) 991 return; 992 s = spltty(); 993 if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { 994 tp->t_state |= TS_BUSY; 995 splx(s); 996 rbp = &tp->t_outq; 997 len = q_to_b(rbp, buf, PCBURST); 998 for (i=0; i<len; i++) 999 if (buf[i]) ansi_put(scp, buf[i]); 1000 s = spltty(); 1001 tp->t_state &= ~TS_BUSY; 1002 if (rbp->c_cc) { 1003 tp->t_state |= TS_TIMEOUT; 1004 timeout((timeout_t)ttrstrt, (caddr_t)tp, 1); 1005 } 1006 if (rbp->c_cc <= tp->t_lowat) { 1007 if (tp->t_state & TS_ASLEEP) { 1008 tp->t_state &= ~TS_ASLEEP; 1009 wakeup((caddr_t)rbp); 1010 } 1011 selwakeup(&tp->t_wsel); 1012 } 1013 } 1014 splx(s); 1015 1016#else /* __FreeBSD__ & __386BSD__ */ 1017 1018 int c, s; 1019 scr_stat *scp = get_scr_stat(tp->t_dev); 1020 1021 if (scp->status & SLKED) 1022 return; 1023 s = spltty(); 1024 if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) 1025 for (;;) { 1026 if (RB_LEN(&tp->t_out) <= tp->t_lowat) { 1027 if (tp->t_state & TS_ASLEEP) { 1028 tp->t_state &= ~TS_ASLEEP; 1029 wakeup((caddr_t)&tp->t_out); 1030 } 1031 if (tp->t_wsel) { 1032 selwakeup(tp->t_wsel, 1033 tp->t_state & TS_WCOLL); 1034 tp->t_wsel = 0; 1035 tp->t_state &= ~TS_WCOLL; 1036 } 1037 } 1038 if (RB_LEN(&tp->t_out) == 0) 1039 break; 1040 if (scp->status & SLKED) 1041 break; 1042 c = getc(&tp->t_out); 1043 tp->t_state |= TS_BUSY; 1044 splx(s); 1045 ansi_put(scp, c); 1046 s = spltty(); 1047 tp->t_state &= ~TS_BUSY; 1048 } 1049 splx(s); 1050#endif 1051} 1052 1053 1054void pccnprobe(struct consdev *cp) 1055{ 1056 int maj; 1057 1058 /* locate the major number */ 1059 for (maj = 0; maj < nchrdev; maj++) 1060 if ((void*)cdevsw[maj].d_open == (void*)pcopen) 1061 break; 1062 1063 /* initialize required fields */ 1064 cp->cn_dev = makedev(maj, NCONS); 1065 cp->cn_pri = CN_INTERNAL; 1066#if defined(__FreeBSD__) || defined(__386BSD__) 1067 cp->cn_tp = CONSOLE_TTY; 1068#endif 1069} 1070 1071 1072void pccninit(struct consdev *cp) 1073{ 1074 scinit(); 1075} 1076 1077 1078void pccnputc(dev_t dev, char c) 1079{ 1080 if (c == '\n') 1081 scput('\r'); 1082 scput(c); 1083 if (cur_console == &console[0]) { 1084 int pos = cur_console->crtat - cur_console->crt_base; 1085 if (pos != cur_cursor_pos) { 1086 cur_cursor_pos = pos; 1087 outb(crtc_addr,14); 1088 outb(crtc_addr+1,pos >> 8); 1089 outb(crtc_addr,15); 1090 outb(crtc_addr+1,pos&0xff); 1091 } 1092 } 1093} 1094 1095 1096int pccngetc(dev_t dev) 1097{ 1098 int s = spltty(); /* block scintr while we poll */ 1099 int c = scgetc(0); 1100 splx(s); 1101 if (c == '\r') c = '\n'; 1102 return(c); 1103} 1104 1105#if defined(FADE_SAVER) 1106static void scrn_saver(int test) 1107{ 1108 static int count = 0; 1109 int i; 1110 1111 if (test) { 1112 scrn_blanked = 1; 1113 if (count < 64) { 1114 outb(PIXMASK, 0xFF); /* no pixelmask */ 1115 outb(PALWADR, 0x00); 1116 outb(PALDATA, 0); 1117 outb(PALDATA, 0); 1118 outb(PALDATA, 0); 1119 for (i = 3; i < 768; i++) { 1120 if (palette[i] - count > 15) 1121 outb(PALDATA, palette[i]-count); 1122 else 1123 outb(PALDATA, 15); 1124 } 1125 inb(crtc_addr+6); /* reset flip/flop */ 1126 outb(ATC, 0x20); /* enable palette */ 1127 count++; 1128 } 1129 } 1130 else { 1131 count = scrn_blanked = 0; 1132 load_palette(); 1133 } 1134} 1135#endif 1136 1137#if defined(BLANK_SAVER) 1138 u_char val; 1139 if (test) { 1140 scrn_blanked = 1; 1141 outb(TSIDX, 0x01); val = inb(TSREG); 1142 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 1143 } 1144 else { 1145 scrn_blanked = 0; 1146 outb(TSIDX, 0x01); val = inb(TSREG); 1147 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 1148 } 1149#endif 1150 1151#if defined(STAR_SAVER) || defined(SNAKE_SAVER) 1152static u_long rand_next = 1; 1153 1154static int rand() 1155{ 1156 return ((rand_next = rand_next * 1103515245 + 12345) & 0x7FFFFFFF); 1157} 1158#endif 1159 1160#if defined(STAR_SAVER) 1161/* 1162 * Alternate saver that got its inspiration from a well known utility 1163 * package for an unfamous OS. 1164 */ 1165 1166#define NUM_STARS 50 1167 1168static void scrn_saver(int test) 1169{ 1170 scr_stat *scp = cur_console; 1171 int cell, i; 1172 char pattern[] = {"...........++++*** "}; 1173 char colors[] = {FG_DARKGREY, FG_LIGHTGREY, 1174 FG_WHITE, FG_LIGHTCYAN}; 1175 static u_short stars[NUM_STARS][2]; 1176 1177 if (test) { 1178 if (!scrn_blanked) { 1179 bcopy(Crtat, scp->scr_buf, 1180 scp->xsize * scp->ysize * 2); 1181 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat, 1182 scp->xsize * scp->ysize); 1183 set_border(0); 1184 i = scp->ysize * scp->xsize + 5; 1185 outb(crtc_addr, 14); 1186 outb(crtc_addr+1, i >> 8); 1187 outb(crtc_addr, 15); 1188 outb(crtc_addr+1, i & 0xff); 1189 scrn_blanked = 1; 1190 for(i=0; i<NUM_STARS; i++) { 1191 stars[i][0] = 1192 rand() % (scp->xsize*scp->ysize); 1193 stars[i][1] = 0; 1194 } 1195 } 1196 cell = rand() % NUM_STARS; 1197 *((u_short*)(Crtat + stars[cell][0])) = 1198 scr_map[pattern[stars[cell][1]]] | 1199 colors[rand()%sizeof(colors)] << 8; 1200 if ((stars[cell][1]+=(rand()%4)) >= sizeof(pattern)-1) { 1201 stars[cell][0] = rand() % (scp->xsize*scp->ysize); 1202 stars[cell][1] = 0; 1203 } 1204 } 1205 else { 1206 if (scrn_blanked) { 1207 bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2); 1208 cur_cursor_pos = -1; 1209 set_border(scp->border); 1210 scrn_blanked = 0; 1211 } 1212 } 1213} 1214#endif 1215 1216#if defined(SNAKE_SAVER) 1217/* 1218 * alternative screen saver for cards that do not like blanking 1219 */ 1220 1221static void scrn_saver(int test) 1222{ 1223 const char saves[] = {"FreeBSD"}; 1224 static u_char *savs[sizeof(saves)-1]; 1225 static int dirx, diry; 1226 int f; 1227 scr_stat *scp = cur_console; 1228 1229 if (test) { 1230 if (!scrn_blanked) { 1231 bcopy(Crtat, scp->scr_buf, 1232 scp->xsize * scp->ysize * 2); 1233 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], 1234 Crtat, scp->xsize * scp->ysize); 1235 set_border(0); 1236 dirx = (scp->xpos ? 1 : -1); 1237 diry = (scp->ypos ? 1238 scp->xsize : -scp->xsize); 1239 for (f=0; f< sizeof(saves)-1; f++) 1240 savs[f] = (u_char *)Crtat + 2 * 1241 (scp->xpos+scp->ypos*scp->xsize); 1242 *(savs[0]) = scr_map[*saves]; 1243 f = scp->ysize * scp->xsize + 5; 1244 outb(crtc_addr, 14); 1245 outb(crtc_addr+1, f >> 8); 1246 outb(crtc_addr, 15); 1247 outb(crtc_addr+1, f & 0xff); 1248 scrn_blanked = 1; 1249 } 1250 if (scrn_blanked++ < 4) 1251 return; 1252 scrn_blanked = 1; 1253 *(savs[sizeof(saves)-2]) = scr_map[0x20]; 1254 for (f=sizeof(saves)-2; f > 0; f--) 1255 savs[f] = savs[f-1]; 1256 f = (savs[0] - (u_char *)Crtat) / 2; 1257 if ((f % scp->xsize) == 0 || 1258 (f % scp->xsize) == scp->xsize - 1 || 1259 (rand() % 50) == 0) 1260 dirx = -dirx; 1261 if ((f / scp->xsize) == 0 || 1262 (f / scp->xsize) == scp->ysize - 1 || 1263 (rand() % 20) == 0) 1264 diry = -diry; 1265 savs[0] += 2*dirx + 2*diry; 1266 for (f=sizeof(saves)-2; f>=0; f--) 1267 *(savs[f]) = scr_map[saves[f]]; 1268 } 1269 else { 1270 if (scrn_blanked) { 1271 bcopy(scp->scr_buf, Crtat, 1272 scp->xsize * scp->ysize * 2); 1273 cur_cursor_pos = -1; 1274 set_border(scp->border); 1275 scrn_blanked = 0; 1276 } 1277 } 1278} 1279#endif 1280 1281static void cursor_shape(int start, int end) 1282{ 1283 outb(crtc_addr, 10); 1284 outb(crtc_addr+1, start & 0xFF); 1285 outb(crtc_addr, 11); 1286 outb(crtc_addr+1, end & 0xFF); 1287} 1288 1289 1290#if !defined(FAT_CURSOR) 1291static void get_cursor_shape(int *start, int *end) 1292{ 1293 outb(crtc_addr, 10); 1294 *start = inb(crtc_addr+1) & 0x1F; 1295 outb(crtc_addr, 11); 1296 *end = inb(crtc_addr+1) & 0x1F; 1297} 1298#endif 1299 1300 1301static void cursor_pos(int force) 1302{ 1303 int pos; 1304 1305 if (cur_console->status & UNKNOWN_MODE) 1306 return; 1307 if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time)) 1308 scrn_saver(1); 1309 pos = cur_console->crtat - cur_console->crt_base; 1310 if (force || (!scrn_blanked && pos != cur_cursor_pos)) { 1311 cur_cursor_pos = pos; 1312 outb(crtc_addr, 14); 1313 outb(crtc_addr+1, pos>>8); 1314 outb(crtc_addr, 15); 1315 outb(crtc_addr+1, pos&0xff); 1316 } 1317 timeout((timeout_t)cursor_pos, 0, hz/20); 1318} 1319 1320 1321static void clear_screen(scr_stat *scp) 1322{ 1323 move_crsr(scp, 0, 0); 1324 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1325 scp->xsize * scp->ysize); 1326} 1327 1328 1329static int switch_scr(u_int next_scr) 1330{ 1331 if (in_putc) { /* delay switch if in putc */ 1332 delayed_next_scr = next_scr+1; 1333 return 0; 1334 } 1335 if (switch_in_progress && 1336 (cur_console->proc != pfind(cur_console->pid))) 1337 switch_in_progress = 0; 1338 1339 if (next_scr >= NCONS || switch_in_progress) { 1340 sysbeep(BELL_PITCH, BELL_DURATION); 1341 return EINVAL; 1342 } 1343 1344 /* is the wanted virtual console open ? */ 1345 if (next_scr) { 1346 struct tty *tp = VIRTUAL_TTY(next_scr); 1347 if (!(tp->t_state & TS_ISOPEN)) { 1348 sysbeep(BELL_PITCH, BELL_DURATION); 1349 return EINVAL; 1350 } 1351 } 1352 1353 switch_in_progress = 1; 1354 old_scp = cur_console; 1355 new_scp = &console[next_scr]; 1356 wakeup((caddr_t)&new_scp->smode); 1357 if (new_scp == old_scp) { 1358 switch_in_progress = 0; 1359 return 0; 1360 } 1361 1362 /* has controlling process died? */ 1363 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1364 old_scp->smode.mode = VT_AUTO; 1365 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1366 new_scp->smode.mode = VT_AUTO; 1367 1368 /* check the modes and switch approbiatly */ 1369 if (old_scp->smode.mode == VT_PROCESS) { 1370 old_scp->status |= SWITCH_WAIT_REL; 1371 psignal(old_scp->proc, old_scp->smode.relsig); 1372 } 1373 else { 1374 exchange_scr(); 1375 if (new_scp->smode.mode == VT_PROCESS) { 1376 new_scp->status |= SWITCH_WAIT_ACQ; 1377 psignal(new_scp->proc, new_scp->smode.acqsig); 1378 } 1379 else 1380 switch_in_progress = 0; 1381 } 1382 return 0; 1383} 1384 1385 1386static void exchange_scr(void) 1387{ 1388 struct tty *tp; 1389 1390 bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2); 1391 old_scp->crt_base = old_scp->scr_buf; 1392 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1393 cur_console = new_scp; 1394 set_mode(new_scp); 1395 new_scp->crt_base = Crtat; 1396 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1397 bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2); 1398 update_leds(new_scp->status & LED_MASK); 1399 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1400 shfts = ctls = alts = agrs = metas = 0; 1401 delayed_next_scr = 0; 1402} 1403 1404 1405static void move_crsr(scr_stat *scp, int x, int y) 1406{ 1407 if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize) 1408 return; 1409 scp->xpos = x; 1410 scp->ypos = y; 1411 scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos; 1412} 1413 1414 1415static void move_up(u_short *s, u_short *d, u_int len) 1416{ 1417 s += len; 1418 d += len; 1419 while (len-- > 0) 1420 *--d = *--s; 1421} 1422 1423 1424static void move_down(u_short *s, u_short *d, u_int len) 1425{ 1426 while (len-- > 0) 1427 *d++ = *s++; 1428} 1429 1430 1431static void scan_esc(scr_stat *scp, u_char c) 1432{ 1433 static u_char ansi_col[16] = 1434 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1435 int i, n; 1436 u_short *src, *dst, count; 1437 1438 if (scp->term.esc == 1) { 1439 switch (c) { 1440 1441 case '[': /* Start ESC [ sequence */ 1442 scp->term.esc = 2; 1443 scp->term.last_param = -1; 1444 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1445 scp->term.param[i] = 1; 1446 scp->term.num_param = 0; 1447 return; 1448 1449 case 'M': /* Move cursor up 1 line, scroll if at top */ 1450 if (scp->ypos > 0) 1451 move_crsr(scp, scp->xpos, scp->ypos - 1); 1452 else { 1453 move_up(scp->crt_base, 1454 scp->crt_base + scp->xsize, 1455 (scp->ysize - 1) * scp->xsize); 1456 fillw(scp->term.cur_attr | scr_map[0x20], 1457 scp->crt_base, scp->xsize); 1458 } 1459 break; 1460#if notyet 1461 case 'Q': 1462 scp->term.esc = 4; 1463 break; 1464#endif 1465 case 'c': /* Clear screen & home */ 1466 clear_screen(scp); 1467 break; 1468 } 1469 } 1470 else if (scp->term.esc == 2) { 1471 if (c >= '0' && c <= '9') { 1472 if (scp->term.num_param < MAX_ESC_PAR) { 1473 if (scp->term.last_param != scp->term.num_param) { 1474 scp->term.last_param = scp->term.num_param; 1475 scp->term.param[scp->term.num_param] = 0; 1476 } 1477 else 1478 scp->term.param[scp->term.num_param] *= 10; 1479 scp->term.param[scp->term.num_param] += c - '0'; 1480 return; 1481 } 1482 } 1483 scp->term.num_param = scp->term.last_param + 1; 1484 switch (c) { 1485 1486 case ';': 1487 if (scp->term.num_param < MAX_ESC_PAR) 1488 return; 1489 break; 1490 1491 case '=': 1492 scp->term.esc = 3; 1493 scp->term.last_param = -1; 1494 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1495 scp->term.param[i] = 1; 1496 scp->term.num_param = 0; 1497 return; 1498 1499 case 'A': /* up n rows */ 1500 n = scp->term.param[0]; if (n < 1) n = 1; 1501 move_crsr(scp, scp->xpos, scp->ypos - n); 1502 break; 1503 1504 case 'B': /* down n rows */ 1505 n = scp->term.param[0]; if (n < 1) n = 1; 1506 move_crsr(scp, scp->xpos, scp->ypos + n); 1507 break; 1508 1509 case 'C': /* right n columns */ 1510 n = scp->term.param[0]; if (n < 1) n = 1; 1511 move_crsr(scp, scp->xpos + n, scp->ypos); 1512 break; 1513 1514 case 'D': /* left n columns */ 1515 n = scp->term.param[0]; if (n < 1) n = 1; 1516 move_crsr(scp, scp->xpos - n, scp->ypos); 1517 break; 1518 1519 case 'E': /* cursor to start of line n lines down */ 1520 n = scp->term.param[0]; if (n < 1) n = 1; 1521 move_crsr(scp, 0, scp->ypos + n); 1522 break; 1523 1524 case 'F': /* cursor to start of line n lines up */ 1525 n = scp->term.param[0]; if (n < 1) n = 1; 1526 move_crsr(scp, 0, scp->ypos - n); 1527 break; 1528 1529 case 'f': /* System V consoles .. */ 1530 case 'H': /* Cursor move */ 1531 if (scp->term.num_param == 0) 1532 move_crsr(scp, 0, 0); 1533 else if (scp->term.num_param == 2) 1534 move_crsr(scp, scp->term.param[1] - 1, 1535 scp->term.param[0] - 1); 1536 break; 1537 1538 case 'J': /* Clear all or part of display */ 1539 if (scp->term.num_param == 0) 1540 n = 0; 1541 else 1542 n = scp->term.param[0]; 1543 switch (n) { 1544 case 0: /* clear form cursor to end of display */ 1545 fillw(scp->term.cur_attr | scr_map[0x20], 1546 scp->crtat, scp->crt_base + 1547 scp->xsize * scp->ysize - 1548 scp->crtat); 1549 break; 1550 case 1: /* clear from beginning of display to cursor */ 1551 fillw(scp->term.cur_attr | scr_map[0x20], 1552 scp->crt_base, 1553 scp->crtat - scp->crt_base); 1554 break; 1555 case 2: /* clear entire display */ 1556 clear_screen(scp); 1557 break; 1558 } 1559 break; 1560 1561 case 'K': /* Clear all or part of line */ 1562 if (scp->term.num_param == 0) 1563 n = 0; 1564 else 1565 n = scp->term.param[0]; 1566 switch (n) { 1567 case 0: /* clear form cursor to end of line */ 1568 fillw(scp->term.cur_attr | scr_map[0x20], 1569 scp->crtat, scp->xsize - scp->xpos); 1570 break; 1571 case 1: /* clear from beginning of line to cursor */ 1572 fillw(scp->term.cur_attr|scr_map[0x20], 1573 scp->crtat - (scp->xsize - scp->xpos), 1574 (scp->xsize - scp->xpos) + 1); 1575 break; 1576 case 2: /* clear entire line */ 1577 fillw(scp->term.cur_attr|scr_map[0x20], 1578 scp->crtat - (scp->xsize - scp->xpos), 1579 scp->xsize); 1580 break; 1581 } 1582 break; 1583 1584 case 'L': /* Insert n lines */ 1585 n = scp->term.param[0]; if (n < 1) n = 1; 1586 if (n > scp->ysize - scp->ypos) 1587 n = scp->ysize - scp->ypos; 1588 src = scp->crt_base + scp->ypos * scp->xsize; 1589 dst = src + n * scp->xsize; 1590 count = scp->ysize - (scp->ypos + n); 1591 move_up(src, dst, count * scp->xsize); 1592 fillw(scp->term.cur_attr | scr_map[0x20], src, 1593 n * scp->xsize); 1594 break; 1595 1596 case 'M': /* Delete n lines */ 1597 n = scp->term.param[0]; if (n < 1) n = 1; 1598 if (n > scp->ysize - scp->ypos) 1599 n = scp->ysize - scp->ypos; 1600 dst = scp->crt_base + scp->ypos * scp->xsize; 1601 src = dst + n * scp->xsize; 1602 count = scp->ysize - (scp->ypos + n); 1603 move_down(src, dst, count * scp->xsize); 1604 src = dst + count * scp->xsize; 1605 fillw(scp->term.cur_attr | scr_map[0x20], src, 1606 n * scp->xsize); 1607 break; 1608 1609 case 'P': /* Delete n chars */ 1610 n = scp->term.param[0]; if (n < 1) n = 1; 1611 if (n > scp->xsize - scp->xpos) 1612 n = scp->xsize - scp->xpos; 1613 dst = scp->crtat; 1614 src = dst + n; 1615 count = scp->xsize - (scp->xpos + n); 1616 move_down(src, dst, count); 1617 src = dst + count; 1618 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1619 break; 1620 1621 case '@': /* Insert n chars */ 1622 n = scp->term.param[0]; if (n < 1) n = 1; 1623 if (n > scp->xsize - scp->xpos) 1624 n = scp->xsize - scp->xpos; 1625 src = scp->crtat; 1626 dst = src + n; 1627 count = scp->xsize - (scp->xpos + n); 1628 move_up(src, dst, count); 1629 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1630 break; 1631 1632 case 'S': /* scroll up n lines */ 1633 n = scp->term.param[0]; if (n < 1) n = 1; 1634 bcopy(scp->crt_base + (scp->xsize * n), 1635 scp->crt_base, 1636 scp->xsize * (scp->ysize - n) * 1637 sizeof(u_short)); 1638 fillw(scp->term.cur_attr | scr_map[0x20], 1639 scp->crt_base + scp->xsize * 1640 (scp->ysize - 1), 1641 scp->xsize); 1642 break; 1643 1644 case 'T': /* scroll down n lines */ 1645 n = scp->term.param[0]; if (n < 1) n = 1; 1646 bcopy(scp->crt_base, 1647 scp->crt_base + (scp->xsize * n), 1648 scp->xsize * (scp->ysize - n) * 1649 sizeof(u_short)); 1650 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1651 scp->xsize); 1652 break; 1653 1654 case 'X': /* delete n characters in line */ 1655 n = scp->term.param[0]; if (n < 1) n = 1; 1656 fillw(scp->term.cur_attr | scr_map[0x20], 1657 scp->crt_base + scp->xpos + 1658 ((scp->xsize*scp->ypos) * sizeof(u_short)), n); 1659 break; 1660 1661 case 'Z': /* move n tabs backwards */ 1662 n = scp->term.param[0]; if (n < 1) n = 1; 1663 if ((i = scp->xpos & 0xf8) == scp->xpos) 1664 i -= 8*n; 1665 else 1666 i -= 8*(n-1); 1667 if (i < 0) 1668 i = 0; 1669 move_crsr(scp, i, scp->ypos); 1670 break; 1671 1672 case '`': /* move cursor to column n */ 1673 n = scp->term.param[0]; if (n < 1) n = 1; 1674 move_crsr(scp, n, scp->ypos); 1675 break; 1676 1677 case 'a': /* move cursor n columns to the right */ 1678 n = scp->term.param[0]; if (n < 1) n = 1; 1679 move_crsr(scp, scp->xpos + n, scp->ypos); 1680 break; 1681 1682 case 'd': /* move cursor to row n */ 1683 n = scp->term.param[0]; if (n < 1) n = 1; 1684 move_crsr(scp, scp->xpos, n); 1685 break; 1686 1687 case 'e': /* move cursor n rows down */ 1688 n = scp->term.param[0]; if (n < 1) n = 1; 1689 move_crsr(scp, scp->xpos, scp->ypos + n); 1690 break; 1691 1692 case 'm': /* change attribute */ 1693 if (scp->term.num_param == 0) 1694 n = 0; 1695 else 1696 n = scp->term.param[0]; 1697 switch (n) { 1698 case 0: /* back to normal */ 1699 scp->term.cur_attr = scp->term.std_attr; 1700 break; 1701 case 1: /* highlight (bold) */ 1702 scp->term.cur_attr &= 0xFF00; 1703 scp->term.cur_attr |= 0x0800; 1704 break; 1705 case 4: /* highlight (underline) */ 1706 scp->term.cur_attr &= 0x0F00; 1707 scp->term.cur_attr |= 0x0800; 1708 break; 1709 case 5: /* blink */ 1710 scp->term.cur_attr &= 0xFF00; 1711 scp->term.cur_attr |= 0x8000; 1712 break; 1713 case 7: /* reverse video */ 1714 scp->term.cur_attr = scp->term.rev_attr; 1715 break; 1716 case 30: case 31: case 32: case 33: /* set fg color */ 1717 case 34: case 35: case 36: case 37: 1718 scp->term.cur_attr = (scp->term.cur_attr & 0xF0FF) 1719 | (ansi_col[(n - 30) & 7] << 8); 1720 break; 1721 case 40: case 41: case 42: case 43: /* set bg color */ 1722 case 44: case 45: case 46: case 47: 1723 scp->term.cur_attr = (scp->term.cur_attr & 0x0FFF) 1724 | (ansi_col[(n - 40) & 7] << 12); 1725 break; 1726 } 1727 break; 1728 1729 case 'x': 1730 if (scp->term.num_param == 0) 1731 n = 0; 1732 else 1733 n = scp->term.param[0]; 1734 switch (n) { 1735 case 0: /* reset attributes */ 1736 scp->term.cur_attr = scp->term.std_attr = 1737 current_default->std_attr; 1738 scp->term.rev_attr = current_default->rev_attr; 1739 break; 1740 case 1: /* set ansi background */ 1741 scp->term.cur_attr = scp->term.std_attr = 1742 (scp->term.std_attr & 0x0F00) | 1743 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1744 break; 1745 case 2: /* set ansi foreground */ 1746 scp->term.cur_attr = scp->term.std_attr = 1747 (scp->term.std_attr & 0xF000) | 1748 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1749 break; 1750 case 3: /* set ansi attribute directly */ 1751 scp->term.cur_attr = scp->term.std_attr = 1752 (scp->term.param[1]&0xFF)<<8; 1753 break; 1754 case 5: /* set ansi reverse video background */ 1755 scp->term.rev_attr = 1756 (scp->term.rev_attr & 0x0F00) | 1757 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1758 break; 1759 case 6: /* set ansi reverse video foreground */ 1760 scp->term.rev_attr = 1761 (scp->term.rev_attr & 0xF000) | 1762 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1763 break; 1764 case 7: /* set ansi reverse video directly */ 1765 scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8; 1766 break; 1767 } 1768 break; 1769 1770 case 'z': /* switch to (virtual) console n */ 1771 if (scp->term.num_param == 1) 1772 switch_scr(scp->term.param[0]); 1773 break; 1774 } 1775 } 1776 else if (scp->term.esc == 3) { 1777 if (c >= '0' && c <= '9') { 1778 if (scp->term.num_param < MAX_ESC_PAR) { 1779 if (scp->term.last_param != scp->term.num_param) { 1780 scp->term.last_param = scp->term.num_param; 1781 scp->term.param[scp->term.num_param] = 0; 1782 } 1783 else 1784 scp->term.param[scp->term.num_param] *= 10; 1785 scp->term.param[scp->term.num_param] += c - '0'; 1786 return; 1787 } 1788 } 1789 scp->term.num_param = scp->term.last_param + 1; 1790 switch (c) { 1791 1792 case ';': 1793 if (scp->term.num_param < MAX_ESC_PAR) 1794 return; 1795 break; 1796 1797 case 'A': /* set display border color */ 1798 if (scp->term.num_param == 1) 1799 scp->border=scp->term.param[0] & 0xff; 1800 if (scp == cur_console) 1801 set_border(scp->border); 1802 break; 1803 1804 case 'B': /* set bell pitch and duration */ 1805 if (scp->term.num_param == 2) { 1806 scp->bell_pitch = scp->term.param[0]; 1807 scp->bell_duration = scp->term.param[1]*10; 1808 } 1809 break; 1810 1811 case 'C': /* set cursor shape (start & end line) */ 1812 if (scp->term.num_param == 2) { 1813 scp->cursor_start = scp->term.param[0] & 0x1F; 1814 scp->cursor_end = scp->term.param[1] & 0x1F; 1815 if (scp == cur_console) 1816 cursor_shape(scp->cursor_start, 1817 scp->cursor_end); 1818 } 1819 break; 1820 1821 case 'F': /* set ansi foreground */ 1822 if (scp->term.num_param == 1) 1823 scp->term.cur_attr = scp->term.std_attr = 1824 (scp->term.std_attr & 0xF000) 1825 | ((scp->term.param[0] & 0x0F) << 8); 1826 break; 1827 1828 case 'G': /* set ansi background */ 1829 if (scp->term.num_param == 1) 1830 scp->term.cur_attr = scp->term.std_attr = 1831 (scp->term.std_attr & 0x0F00) 1832 | ((scp->term.param[0] & 0x0F) << 12); 1833 break; 1834 1835 case 'H': /* set ansi reverse video foreground */ 1836 if (scp->term.num_param == 1) 1837 scp->term.rev_attr = 1838 (scp->term.rev_attr & 0xF000) 1839 | ((scp->term.param[0] & 0x0F) << 8); 1840 break; 1841 1842 case 'I': /* set ansi reverse video background */ 1843 if (scp->term.num_param == 1) 1844 scp->term.rev_attr = 1845 (scp->term.rev_attr & 0x0F00) 1846 | ((scp->term.param[0] & 0x0F) << 12); 1847 break; 1848 } 1849 } 1850 scp->term.esc = 0; 1851} 1852 1853 1854static void ansi_put(scr_stat *scp, u_char c) 1855{ 1856 if (scp->status & UNKNOWN_MODE) 1857 return; 1858 1859 /* make screensaver happy */ 1860 if (scp == cur_console) { 1861 scrn_time_stamp = time.tv_sec; 1862 if (scrn_blanked) 1863 scrn_saver(0); 1864 } 1865 in_putc++; 1866 if (scp->term.esc) 1867 scan_esc(scp, c); 1868 else switch(c) { 1869 case 0x1B: /* start escape sequence */ 1870 scp->term.esc = 1; 1871 scp->term.num_param = 0; 1872 break; 1873 case 0x07: 1874 if (scp == cur_console) 1875 sysbeep(scp->bell_pitch, scp->bell_duration); 1876 break; 1877 case '\t': /* non-destructive tab */ 1878 scp->crtat += (8 - scp->xpos % 8); 1879 scp->xpos += (8 - scp->xpos % 8); 1880 break; 1881 case '\b': /* non-destructive backspace */ 1882 if (scp->crtat > scp->crt_base) { 1883 scp->crtat--; 1884 if (scp->xpos > 0) 1885 scp->xpos--; 1886 else { 1887 scp->xpos += scp->xsize - 1; 1888 scp->ypos--; 1889 } 1890 } 1891 break; 1892 case '\r': /* return to pos 0 */ 1893 move_crsr(scp, 0, scp->ypos); 1894 break; 1895 case '\n': /* newline, same pos */ 1896 scp->crtat += scp->xsize; 1897 scp->ypos++; 1898 break; 1899 case '\f': /* form feed, clears screen */ 1900 clear_screen(scp); 1901 break; 1902 default: 1903 /* Print only printables */ 1904 *scp->crtat = (scp->term.cur_attr | scr_map[c]); 1905 scp->crtat++; 1906 if (++scp->xpos >= scp->xsize) { 1907 scp->xpos = 0; 1908 scp->ypos++; 1909 } 1910 break; 1911 } 1912 if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) { 1913 bcopy(scp->crt_base + scp->xsize, scp->crt_base, 1914 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 1915 fillw(scp->term.cur_attr | scr_map[0x20], 1916 scp->crt_base + scp->xsize * (scp->ysize - 1), 1917 scp->xsize); 1918 scp->crtat -= scp->xsize; 1919 scp->ypos--; 1920 } 1921 in_putc--; 1922 if (delayed_next_scr) 1923 switch_scr(delayed_next_scr - 1); 1924} 1925 1926static void scinit(void) 1927{ 1928 u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was; 1929 unsigned cursorat; 1930 int i; 1931 1932 /* 1933 * catch that once in a blue moon occurence when scinit is called 1934 * TWICE, adding the CGA_BUF offset again -> poooff 1935 */ 1936 if (crtat != 0) 1937 return; 1938 /* 1939 * Crtat initialized to point to MONO buffer, if not present change 1940 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds 1941 * in the remapped offset at the "right" time 1942 */ 1943 was = *cp; 1944 *cp = (u_short) 0xA55A; 1945 if (*cp != 0xA55A) { 1946 crtc_addr = MONO_BASE; 1947 } else { 1948 *cp = was; 1949 crtc_addr = COLOR_BASE; 1950 Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short); 1951 } 1952 1953 /* Extract cursor location */ 1954 outb(crtc_addr,14); 1955 cursorat = inb(crtc_addr+1)<<8 ; 1956 outb(crtc_addr,15); 1957 cursorat |= inb(crtc_addr+1); 1958 crtat = Crtat + cursorat; 1959 1960 /* is this a VGA or higher ? */ 1961 outb(crtc_addr, 7); 1962 if (inb(crtc_addr) == 7) 1963 crtc_vga = 1; 1964 1965 current_default = &user_default; 1966 console[0].crtat = crtat; 1967 console[0].crt_base = Crtat; 1968 console[0].term.esc = 0; 1969 console[0].term.std_attr = current_default->std_attr; 1970 console[0].term.rev_attr = current_default->rev_attr; 1971 console[0].term.cur_attr = current_default->std_attr; 1972 console[0].xpos = cursorat % COL; 1973 console[0].ypos = cursorat / COL; 1974 console[0].border = BG_BLACK;; 1975 console[0].xsize = COL; 1976 console[0].ysize = ROW; 1977 console[0].status = 0; 1978 console[0].pid = 0; 1979 console[0].proc = NULL; 1980 console[0].smode.mode = VT_AUTO; 1981 console[0].bell_pitch = BELL_PITCH; 1982 console[0].bell_duration = BELL_DURATION; 1983 kernel_console.esc = 0; 1984 kernel_console.std_attr = kernel_default.std_attr; 1985 kernel_console.rev_attr = kernel_default.rev_attr; 1986 kernel_console.cur_attr = kernel_default.std_attr; 1987 /* initialize mapscrn array to a one to one map */ 1988 for (i=0; i<sizeof(scr_map); i++) 1989 scr_map[i] = i; 1990 clear_screen(&console[0]); 1991} 1992 1993 1994static void scput(u_char c) 1995{ 1996 scr_stat *scp = &console[0]; 1997 term_stat save; 1998 1999 if (crtat == 0) 2000 scinit(); 2001 save = scp->term; 2002 scp->term = kernel_console; 2003 current_default = &kernel_default; 2004 ansi_put(scp, c); 2005 kernel_console = scp->term; 2006 current_default = &user_default; 2007 scp->term = save; 2008} 2009 2010 2011static u_char *get_fstr(u_int c, u_int *len) 2012{ 2013 u_int i; 2014 2015 if (!(c & FKEY)) 2016 return(NULL); 2017 i = (c & 0xFF) - F_FN; 2018 if (i > n_fkey_tab) 2019 return(NULL); 2020 *len = fkey_tab[i].len; 2021 return(fkey_tab[i].str); 2022} 2023 2024 2025static void update_leds(int which) 2026{ 2027 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 2028 2029 kbd_cmd2(KB_SETLEDS, xlate_leds[which & LED_MASK]); 2030} 2031 2032 2033/* 2034 * scgetc(noblock) : get a character from the keyboard. 2035 * If noblock = 0 wait until a key is gotten. Otherwise return NOKEY. 2036 */ 2037u_int scgetc(int noblock) 2038{ 2039 u_char val, code, release; 2040 u_int state, action; 2041 struct key_t *key; 2042 static u_char esc_flag = 0, compose = 0; 2043 static u_int chr = 0; 2044 2045next_code: 2046 kbd_wait(); 2047 /* First see if there is something in the keyboard port */ 2048 if (inb(KB_STAT) & KB_BUF_FULL) 2049 val = inb(KB_DATA); 2050 else if (noblock) 2051 return(NOKEY); 2052 else 2053 goto next_code; 2054 2055 if (cur_console->status & KBD_RAW_MODE) 2056 return val; 2057 2058 code = val & 0x7F; 2059 release = val & 0x80; 2060 2061 switch (esc_flag) { 2062 case 0x00: /* normal scancode */ 2063 switch(code) { 2064 case 0x38: /* left alt (compose key) */ 2065 if (release && compose) { 2066 compose = 0; 2067 if (chr > 255) { 2068 sysbeep(BELL_PITCH, BELL_DURATION); 2069 chr = 0; 2070 } 2071 } 2072 else { 2073 if (!compose) { 2074 compose = 1; 2075 chr = 0; 2076 } 2077 } 2078 break; 2079 case 0x60: 2080 case 0x61: 2081 esc_flag = code; 2082 goto next_code; 2083 } 2084 break; 2085 case 0x60: /* 0xE0 prefix */ 2086 esc_flag = 0; 2087 switch (code) { 2088 case 0x1c: /* right enter key */ 2089 code = 0x59; 2090 break; 2091 case 0x1d: /* right ctrl key */ 2092 code = 0x5a; 2093 break; 2094 case 0x35: /* keypad divide key */ 2095 code = 0x5b; 2096 break; 2097 case 0x37: /* print scrn key */ 2098 code = 0x5c; 2099 break; 2100 case 0x38: /* right alt key (alt gr) */ 2101 code = 0x5d; 2102 break; 2103 case 0x47: /* grey home key */ 2104 code = 0x5e; 2105 break; 2106 case 0x48: /* grey up arrow key */ 2107 code = 0x5f; 2108 break; 2109 case 0x49: /* grey page up key */ 2110 code = 0x60; 2111 break; 2112 case 0x4b: /* grey left arrow key */ 2113 code = 0x61; 2114 break; 2115 case 0x4d: /* grey right arrow key */ 2116 code = 0x62; 2117 break; 2118 case 0x4f: /* grey end key */ 2119 code = 0x63; 2120 break; 2121 case 0x50: /* grey down arrow key */ 2122 code = 0x64; 2123 break; 2124 case 0x51: /* grey page down key */ 2125 code = 0x65; 2126 break; 2127 case 0x52: /* grey insert key */ 2128 code = 0x66; 2129 break; 2130 case 0x53: /* grey delete key */ 2131 code = 0x67; 2132 break; 2133 default: /* ignore everything else */ 2134 goto next_code; 2135 } 2136 break; 2137 case 0x61: /* 0xE1 prefix */ 2138 esc_flag = 0; 2139 if (code == 0x1D) 2140 esc_flag = 0x1D; 2141 goto next_code; 2142 /* NOT REACHED */ 2143 case 0x1D: /* pause / break */ 2144 esc_flag = 0; 2145 if (code != 0x45) 2146 goto next_code; 2147 code = 0x68; 2148 break; 2149 } 2150 2151 if (compose) { 2152 switch (code) { 2153 case 0x47: 2154 case 0x48: /* keypad 7,8,9 */ 2155 case 0x49: 2156 if (!release) 2157 chr = (code - 0x40) + chr*10; 2158 goto next_code; 2159 case 0x4b: 2160 case 0x4c: /* keypad 4,5,6 */ 2161 case 0x4d: 2162 if (!release) 2163 chr = (code - 0x47) + chr*10; 2164 goto next_code; 2165 case 0x4f: 2166 case 0x50: /* keypad 1,2,3 */ 2167 case 0x51: 2168 if (!release) 2169 chr = (code - 0x4e) + chr*10; 2170 goto next_code; 2171 case 0x52: /* keypad 0 */ 2172 if (!release) 2173 chr *= 10; 2174 goto next_code; 2175 case 0x38: /* left alt key */ 2176 break; 2177 default: 2178 if (chr) { 2179 compose = chr = 0; 2180 sysbeep(BELL_PITCH, BELL_DURATION); 2181 goto next_code; 2182 } 2183 break; 2184 } 2185 } 2186 2187 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2188 if ((!agrs && (cur_console->status & ALKED)) 2189 || (agrs && !(cur_console->status & ALKED))) 2190 code += ALTGR_OFFSET; 2191 key = &key_map.key[code]; 2192 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2193 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2194 state ^= 1; 2195 2196 /* Check for make/break */ 2197 action = key->map[state]; 2198 if (release) { /* key released */ 2199 if (key->spcl & 0x80) { 2200 switch (action) { 2201 case LSH: 2202 shfts &= ~1; 2203 break; 2204 case RSH: 2205 shfts &= ~2; 2206 break; 2207 case LCTR: 2208 ctls &= ~1; 2209 break; 2210 case RCTR: 2211 ctls &= ~2; 2212 break; 2213 case LALT: 2214 alts &= ~1; 2215 break; 2216 case RALT: 2217 alts &= ~2; 2218 break; 2219 case NLK: 2220 nlkcnt = 0; 2221 break; 2222 case CLK: 2223 clkcnt = 0; 2224 break; 2225 case SLK: 2226 slkcnt = 0; 2227 break; 2228 case ASH: 2229 agrs = 0; 2230 break; 2231 case ALK: 2232 alkcnt = 0; 2233 break; 2234 case META: 2235 metas = 0; 2236 break; 2237 } 2238 } 2239 if (chr && !compose) { 2240 action = chr; 2241 chr = 0; 2242 return(action); 2243 } 2244 } else { 2245 /* key pressed */ 2246 if (key->spcl & (0x80>>state)) { 2247 switch (action) { 2248 /* LOCKING KEYS */ 2249 case NLK: 2250 if (!nlkcnt) { 2251 nlkcnt++; 2252 if (cur_console->status & NLKED) 2253 cur_console->status &= ~NLKED; 2254 else 2255 cur_console->status |= NLKED; 2256 update_leds(cur_console->status & LED_MASK); 2257 } 2258 break; 2259 case CLK: 2260 if (!clkcnt) { 2261 clkcnt++; 2262 if (cur_console->status & CLKED) 2263 cur_console->status &= ~CLKED; 2264 else 2265 cur_console->status |= CLKED; 2266 update_leds(cur_console->status & LED_MASK); 2267 } 2268 break; 2269 case SLK: 2270 if (!slkcnt) { 2271 slkcnt++; 2272 if (cur_console->status & SLKED) { 2273 cur_console->status &= ~SLKED; 2274 pcstart(VIRTUAL_TTY(get_scr_num())); 2275 } 2276 else 2277 cur_console->status |= SLKED; 2278 update_leds(cur_console->status & LED_MASK); 2279 } 2280 break; 2281 case ALK: 2282 if (!alkcnt) { 2283 alkcnt++; 2284 if (cur_console->status & ALKED) 2285 cur_console->status &= ~ALKED; 2286 else 2287 cur_console->status |= ALKED; 2288 } 2289 break; 2290 2291 /* NON-LOCKING KEYS */ 2292 case NOP: 2293 break; 2294 case RBT: 2295#if defined(__FreeBSD__) 2296 shutdown_nice(); 2297#else 2298 cpu_reset(); 2299#endif 2300 break; 2301 case DBG: 2302#if DDB > 0 /* try to switch to console 0 */ 2303 if (cur_console->smode.mode == VT_AUTO && 2304 console[0].smode.mode == VT_AUTO) 2305 switch_scr(0); 2306 Debugger("manual escape to debugger"); 2307 return(NOKEY); 2308#else 2309 printf("No debugger in kernel\n"); 2310#endif 2311 break; 2312 case LSH: 2313 shfts |= 1; 2314 break; 2315 case RSH: 2316 shfts |= 2; 2317 break; 2318 case LCTR: 2319 ctls |= 1; 2320 break; 2321 case RCTR: 2322 ctls |= 2; 2323 break; 2324 case LALT: 2325 alts |= 1; 2326 break; 2327 case RALT: 2328 alts |= 2; 2329 break; 2330 case ASH: 2331 agrs = 1; 2332 break; 2333 case META: 2334 metas = 1; 2335 break; 2336 case NEXT: 2337 switch_scr((get_scr_num()+1)%NCONS); 2338 break; 2339 default: 2340 if (action >= F_SCR && action <= L_SCR) { 2341 switch_scr(action - F_SCR); 2342 break; 2343 } 2344 if (action >= F_FN && action <= L_FN) 2345 action |= FKEY; 2346 return(action); 2347 } 2348 } 2349 else { 2350 if (metas) 2351 action |= MKEY; 2352 return(action); 2353 } 2354 } 2355 goto next_code; 2356} 2357 2358 2359int getchar(void) 2360{ 2361 u_char thechar; 2362 int s; 2363 2364 polling = 1; 2365 s = splhigh(); 2366 scput('>'); 2367 thechar = (u_char) scgetc(0); 2368 polling = 0; 2369 splx(s); 2370 switch (thechar) { 2371 default: 2372 if (thechar >= scr_map[0x20]) 2373 scput(thechar); 2374 return(thechar); 2375 case cr: 2376 case lf: 2377 scput(cr); scput(lf); 2378 return(lf); 2379 case bs: 2380 case del: 2381 scput(bs); scput(scr_map[0x20]); scput(bs); 2382 return(thechar); 2383 case cntld: 2384 scput('^'); scput('D'); scput('\r'); scput('\n'); 2385 return(0); 2386 } 2387} 2388 2389 2390u_int sgetc(int noblock) 2391{ 2392 return (scgetc(noblock) & 0xff); 2393} 2394 2395int pcmmap(dev_t dev, int offset, int nprot) 2396{ 2397 if (offset > 0x20000) 2398 return EINVAL; 2399 return i386_btop((VIDEOMEM + offset)); 2400} 2401 2402 2403static void kbd_wait(void) 2404{ 2405 int i; 2406 2407 for (i=0; i<1000; i++) { /* up to 10 msec */ 2408 if ((inb(KB_STAT) & KB_READY) == 0) 2409 break; 2410 DELAY (10); 2411 } 2412} 2413 2414 2415static void kbd_cmd(u_char command) 2416{ 2417 kbd_wait(); 2418 outb(KB_DATA, command); 2419} 2420 2421 2422static void kbd_cmd2(u_char command, u_char arg) 2423{ 2424 int r, s = spltty(); 2425 do { 2426 kbd_cmd(command); 2427 r = kbd_reply(); 2428 if (r == KB_ACK) { 2429 kbd_cmd(arg & 0x7f); 2430 r = kbd_reply(); 2431 } 2432 } while (r != KB_ACK); 2433 splx(s); 2434} 2435 2436 2437static int kbd_reply() 2438{ 2439 int i; 2440 2441 kbd_wait(); 2442 for (i=0; i<50000; i++) { /* at least 300 msec, 500 msec enough */ 2443 if (inb(KB_STAT) & KB_BUF_FULL) 2444 return ((u_char) inb(KB_DATA)); 2445 DELAY (10); 2446 } 2447 return(-1); 2448} 2449 2450 2451static void set_mode(scr_stat *scp) 2452{ 2453 u_char byte; 2454 int s; 2455 2456 if (scp != cur_console) 2457 return; 2458 2459 /* (re)activate cursor */ 2460 untimeout((timeout_t)cursor_pos, 0); 2461 cursor_pos(1); 2462 2463 /* change cursor type if set */ 2464 if (scp->cursor_start != -1 && scp->cursor_end != -1) 2465 cursor_shape(scp->cursor_start, scp->cursor_end); 2466 2467 /* mode change only on VGA's */ 2468 if (!crtc_vga) 2469 return; 2470 2471 /* setup video hardware for the given mode */ 2472 s = splhigh(); 2473 switch(scp->mode) { 2474 case TEXT80x25: 2475 outb(crtc_addr, 9); byte = inb(crtc_addr+1); 2476 outb(crtc_addr, 9); outb(crtc_addr+1, byte | 0x0F); 2477 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* select font 0 */ 2478 break; 2479 case TEXT80x50: 2480 outb(crtc_addr, 9); byte = inb(crtc_addr+1); 2481 outb(crtc_addr, 9); outb(crtc_addr+1, (byte & 0xF0) | 0x07); 2482 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* select font 1 */ 2483 break; 2484 default: 2485 break; 2486 } 2487 splx(s); 2488 2489 /* set border color for this (virtual) console */ 2490 set_border(scp->border); 2491 return; 2492} 2493 2494 2495static void set_border(int color) 2496{ 2497 inb(crtc_addr+6); /* reset flip-flop */ 2498 outb(ATC, 0x11); outb(ATC, color); 2499 inb(crtc_addr+6); /* reset flip-flop */ 2500 outb(ATC, 0x20); /* enable Palette */ 2501} 2502 2503static void load_font(int segment, int size, char* font) 2504{ 2505 int ch, line, s; 2506 u_char val; 2507 2508 outb(TSIDX, 0x01); val = inb(TSREG); /* blank screen */ 2509 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 2510 2511 /* setup vga for loading fonts (graphics plane mode) */ 2512 s = splhigh(); 2513 inb(crtc_addr+6); /* reset flip/flop */ 2514 outb(ATC, 0x30); outb(ATC, 0x01); 2515 outb(TSIDX, 0x02); outb(TSREG, 0x04); 2516 outb(TSIDX, 0x04); outb(TSREG, 0x06); 2517 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 2518 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 2519 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); /* addr = a0000, 64kb */ 2520 splx(s); 2521 for (ch=0; ch < 256; ch++) 2522 for (line=0; line < size; line++) 2523 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line) = 2524 font[(ch*size)+line]; 2525 /* setup vga for text mode again */ 2526 s = splhigh(); 2527 inb(crtc_addr+6); /* reset flip/flop */ 2528 outb(ATC, 0x30); outb(ATC, 0x0C); 2529 outb(TSIDX, 0x02); outb(TSREG, 0x03); 2530 outb(TSIDX, 0x04); outb(TSREG, 0x02); 2531 outb(GDCIDX, 0x04); outb(GDCREG, 0x00); 2532 outb(GDCIDX, 0x05); outb(GDCREG, 0x10); 2533 if (crtc_addr == MONO_BASE) { 2534 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */ 2535 } 2536 else { 2537 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */ 2538 } 2539 splx(s); 2540 outb(TSIDX, 0x01); val = inb(TSREG); /* unblank screen */ 2541 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 2542} 2543 2544 2545static void load_palette(void) 2546{ 2547 int i; 2548 2549 outb(PIXMASK, 0xFF); /* no pixelmask */ 2550 outb(PALWADR, 0x00); 2551 for (i=0x00; i<0x300; i++) 2552 outb(PALDATA, palette[i]); 2553 inb(crtc_addr+6); /* reset flip/flop */ 2554 outb(ATC, 0x20); /* enable palette */ 2555} 2556 2557static void save_palette(void) 2558{ 2559 int i; 2560 2561 outb(PALRADR, 0x00); 2562 for (i=0x00; i<0x300; i++) 2563 palette[i] = inb(PALDATA); 2564 inb(crtc_addr+6); /* reset flip/flop */ 2565} 2566 2567 2568static void change_winsize(struct tty *tp, int x, int y) 2569{ 2570 if (tp->t_winsize.ws_col != x || tp->t_winsize.ws_row != y) { 2571 tp->t_winsize.ws_col = x; 2572 tp->t_winsize.ws_row = y; 2573 pgsignal(tp->t_pgrp, SIGWINCH, 1); 2574 } 2575} 2576 2577#endif /* NSC */ 2578