syscons.c revision 1063
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.27 1994/02/01 06:17:36 nate Exp $ 39 * 40 */ 41 42/* #define FADE_SAVER */ 43/* #define BLANK_SAVER */ 44/* #define STAR_SAVER */ 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) 1152static u_long rand_next = 1; 1153 1154static int rand() 1155{ 1156 return ((rand_next = rand_next * 1103515245 + 12345) & 0x7FFFFFFF); 1157} 1158 1159/* 1160 * Alternate saver that got its inspiration from a well known utility 1161 * package for an unfamous OS. 1162 */ 1163 1164#define NUM_STARS 50 1165 1166static void scrn_saver(int test) 1167{ 1168 scr_stat *scp = cur_console; 1169 int cell, i; 1170 char pattern[] = {"...........++++*** "}; 1171 char colors[] = {FG_DARKGREY, FG_LIGHTGREY, 1172 FG_WHITE, FG_LIGHTCYAN}; 1173 static u_short stars[NUM_STARS][2]; 1174 1175 if (test) { 1176 if (!scrn_blanked) { 1177 bcopy(Crtat, scp->scr_buf, 1178 scp->xsize * scp->ysize * 2); 1179 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat, 1180 scp->xsize * scp->ysize); 1181 set_border(0); 1182 i = scp->ysize * scp->xsize + 5; 1183 outb(crtc_addr, 14); 1184 outb(crtc_addr+1, i >> 8); 1185 outb(crtc_addr, 15); 1186 outb(crtc_addr+1, i & 0xff); 1187 scrn_blanked = 1; 1188 for(i=0; i<NUM_STARS; i++) { 1189 stars[i][0] = 1190 rand() % (scp->xsize*scp->ysize); 1191 stars[i][1] = 0; 1192 } 1193 } 1194 cell = rand() % NUM_STARS; 1195 *((u_short*)(Crtat + stars[cell][0])) = 1196 scr_map[pattern[stars[cell][1]]] | 1197 colors[rand()%sizeof(colors)] << 8; 1198 if ((stars[cell][1]+=(rand()%4)) >= sizeof(pattern)-1) { 1199 stars[cell][0] = rand() % (scp->xsize*scp->ysize); 1200 stars[cell][1] = 0; 1201 } 1202 } 1203 else { 1204 if (scrn_blanked) { 1205 bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2); 1206 cur_cursor_pos = -1; 1207 set_border(scp->border); 1208 scrn_blanked = 0; 1209 } 1210 } 1211} 1212#endif 1213 1214 1215static void cursor_shape(int start, int end) 1216{ 1217 outb(crtc_addr, 10); 1218 outb(crtc_addr+1, start & 0xFF); 1219 outb(crtc_addr, 11); 1220 outb(crtc_addr+1, end & 0xFF); 1221} 1222 1223 1224#if !defined(FAT_CURSOR) 1225static void get_cursor_shape(int *start, int *end) 1226{ 1227 outb(crtc_addr, 10); 1228 *start = inb(crtc_addr+1) & 0x1F; 1229 outb(crtc_addr, 11); 1230 *end = inb(crtc_addr+1) & 0x1F; 1231} 1232#endif 1233 1234 1235static void cursor_pos(int force) 1236{ 1237 int pos; 1238 1239 if (cur_console->status & UNKNOWN_MODE) 1240 return; 1241 if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time)) 1242 scrn_saver(1); 1243 pos = cur_console->crtat - cur_console->crt_base; 1244 if (force || (!scrn_blanked && pos != cur_cursor_pos)) { 1245 cur_cursor_pos = pos; 1246 outb(crtc_addr, 14); 1247 outb(crtc_addr+1, pos>>8); 1248 outb(crtc_addr, 15); 1249 outb(crtc_addr+1, pos&0xff); 1250 } 1251 timeout((timeout_t)cursor_pos, 0, hz/20); 1252} 1253 1254 1255static void clear_screen(scr_stat *scp) 1256{ 1257 move_crsr(scp, 0, 0); 1258 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1259 scp->xsize * scp->ysize); 1260} 1261 1262 1263static int switch_scr(u_int next_scr) 1264{ 1265 if (in_putc) { /* delay switch if in putc */ 1266 delayed_next_scr = next_scr+1; 1267 return 0; 1268 } 1269 if (switch_in_progress && 1270 (cur_console->proc != pfind(cur_console->pid))) 1271 switch_in_progress = 0; 1272 1273 if (next_scr >= NCONS || switch_in_progress) { 1274 sysbeep(BELL_PITCH, BELL_DURATION); 1275 return EINVAL; 1276 } 1277 1278 /* is the wanted virtual console open ? */ 1279 if (next_scr) { 1280 struct tty *tp = VIRTUAL_TTY(next_scr); 1281 if (!(tp->t_state & TS_ISOPEN)) { 1282 sysbeep(BELL_PITCH, BELL_DURATION); 1283 return EINVAL; 1284 } 1285 } 1286 1287 switch_in_progress = 1; 1288 old_scp = cur_console; 1289 new_scp = &console[next_scr]; 1290 wakeup((caddr_t)&new_scp->smode); 1291 if (new_scp == old_scp) { 1292 switch_in_progress = 0; 1293 return 0; 1294 } 1295 1296 /* has controlling process died? */ 1297 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1298 old_scp->smode.mode = VT_AUTO; 1299 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1300 new_scp->smode.mode = VT_AUTO; 1301 1302 /* check the modes and switch approbiatly */ 1303 if (old_scp->smode.mode == VT_PROCESS) { 1304 old_scp->status |= SWITCH_WAIT_REL; 1305 psignal(old_scp->proc, old_scp->smode.relsig); 1306 } 1307 else { 1308 exchange_scr(); 1309 if (new_scp->smode.mode == VT_PROCESS) { 1310 new_scp->status |= SWITCH_WAIT_ACQ; 1311 psignal(new_scp->proc, new_scp->smode.acqsig); 1312 } 1313 else 1314 switch_in_progress = 0; 1315 } 1316 return 0; 1317} 1318 1319 1320static void exchange_scr(void) 1321{ 1322 struct tty *tp; 1323 1324 bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2); 1325 old_scp->crt_base = old_scp->scr_buf; 1326 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1327 cur_console = new_scp; 1328 set_mode(new_scp); 1329 new_scp->crt_base = Crtat; 1330 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1331 bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2); 1332 update_leds(new_scp->status & LED_MASK); 1333 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1334 shfts = ctls = alts = agrs = metas = 0; 1335 delayed_next_scr = 0; 1336} 1337 1338 1339static void move_crsr(scr_stat *scp, int x, int y) 1340{ 1341 if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize) 1342 return; 1343 scp->xpos = x; 1344 scp->ypos = y; 1345 scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos; 1346} 1347 1348 1349static void move_up(u_short *s, u_short *d, u_int len) 1350{ 1351 s += len; 1352 d += len; 1353 while (len-- > 0) 1354 *--d = *--s; 1355} 1356 1357 1358static void move_down(u_short *s, u_short *d, u_int len) 1359{ 1360 while (len-- > 0) 1361 *d++ = *s++; 1362} 1363 1364 1365static void scan_esc(scr_stat *scp, u_char c) 1366{ 1367 static u_char ansi_col[16] = 1368 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1369 int i, n; 1370 u_short *src, *dst, count; 1371 1372 if (scp->term.esc == 1) { 1373 switch (c) { 1374 1375 case '[': /* Start ESC [ sequence */ 1376 scp->term.esc = 2; 1377 scp->term.last_param = -1; 1378 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1379 scp->term.param[i] = 1; 1380 scp->term.num_param = 0; 1381 return; 1382 1383 case 'M': /* Move cursor up 1 line, scroll if at top */ 1384 if (scp->ypos > 0) 1385 move_crsr(scp, scp->xpos, scp->ypos - 1); 1386 else { 1387 move_up(scp->crt_base, 1388 scp->crt_base + scp->xsize, 1389 (scp->ysize - 1) * scp->xsize); 1390 fillw(scp->term.cur_attr | scr_map[0x20], 1391 scp->crt_base, scp->xsize); 1392 } 1393 break; 1394#if notyet 1395 case 'Q': 1396 scp->term.esc = 4; 1397 break; 1398#endif 1399 case 'c': /* Clear screen & home */ 1400 clear_screen(scp); 1401 break; 1402 } 1403 } 1404 else if (scp->term.esc == 2) { 1405 if (c >= '0' && c <= '9') { 1406 if (scp->term.num_param < MAX_ESC_PAR) { 1407 if (scp->term.last_param != scp->term.num_param) { 1408 scp->term.last_param = scp->term.num_param; 1409 scp->term.param[scp->term.num_param] = 0; 1410 } 1411 else 1412 scp->term.param[scp->term.num_param] *= 10; 1413 scp->term.param[scp->term.num_param] += c - '0'; 1414 return; 1415 } 1416 } 1417 scp->term.num_param = scp->term.last_param + 1; 1418 switch (c) { 1419 1420 case ';': 1421 if (scp->term.num_param < MAX_ESC_PAR) 1422 return; 1423 break; 1424 1425 case '=': 1426 scp->term.esc = 3; 1427 scp->term.last_param = -1; 1428 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1429 scp->term.param[i] = 1; 1430 scp->term.num_param = 0; 1431 return; 1432 1433 case 'A': /* up n rows */ 1434 n = scp->term.param[0]; if (n < 1) n = 1; 1435 move_crsr(scp, scp->xpos, scp->ypos - n); 1436 break; 1437 1438 case 'B': /* down n rows */ 1439 n = scp->term.param[0]; if (n < 1) n = 1; 1440 move_crsr(scp, scp->xpos, scp->ypos + n); 1441 break; 1442 1443 case 'C': /* right n columns */ 1444 n = scp->term.param[0]; if (n < 1) n = 1; 1445 move_crsr(scp, scp->xpos + n, scp->ypos); 1446 break; 1447 1448 case 'D': /* left n columns */ 1449 n = scp->term.param[0]; if (n < 1) n = 1; 1450 move_crsr(scp, scp->xpos - n, scp->ypos); 1451 break; 1452 1453 case 'E': /* cursor to start of line n lines down */ 1454 n = scp->term.param[0]; if (n < 1) n = 1; 1455 move_crsr(scp, 0, scp->ypos + n); 1456 break; 1457 1458 case 'F': /* cursor to start of line n lines up */ 1459 n = scp->term.param[0]; if (n < 1) n = 1; 1460 move_crsr(scp, 0, scp->ypos - n); 1461 break; 1462 1463 case 'f': /* System V consoles .. */ 1464 case 'H': /* Cursor move */ 1465 if (scp->term.num_param == 0) 1466 move_crsr(scp, 0, 0); 1467 else if (scp->term.num_param == 2) 1468 move_crsr(scp, scp->term.param[1] - 1, 1469 scp->term.param[0] - 1); 1470 break; 1471 1472 case 'J': /* Clear all or part of display */ 1473 if (scp->term.num_param == 0) 1474 n = 0; 1475 else 1476 n = scp->term.param[0]; 1477 switch (n) { 1478 case 0: /* clear form cursor to end of display */ 1479 fillw(scp->term.cur_attr | scr_map[0x20], 1480 scp->crtat, scp->crt_base + 1481 scp->xsize * scp->ysize - 1482 scp->crtat); 1483 break; 1484 case 1: /* clear from beginning of display to cursor */ 1485 fillw(scp->term.cur_attr | scr_map[0x20], 1486 scp->crt_base, 1487 scp->crtat - scp->crt_base); 1488 break; 1489 case 2: /* clear entire display */ 1490 clear_screen(scp); 1491 break; 1492 } 1493 break; 1494 1495 case 'K': /* Clear all or part of line */ 1496 if (scp->term.num_param == 0) 1497 n = 0; 1498 else 1499 n = scp->term.param[0]; 1500 switch (n) { 1501 case 0: /* clear form cursor to end of line */ 1502 fillw(scp->term.cur_attr | scr_map[0x20], 1503 scp->crtat, scp->xsize - scp->xpos); 1504 break; 1505 case 1: /* clear from beginning of line to cursor */ 1506 fillw(scp->term.cur_attr|scr_map[0x20], 1507 scp->crtat - (scp->xsize - scp->xpos), 1508 (scp->xsize - scp->xpos) + 1); 1509 break; 1510 case 2: /* clear entire line */ 1511 fillw(scp->term.cur_attr|scr_map[0x20], 1512 scp->crtat - (scp->xsize - scp->xpos), 1513 scp->xsize); 1514 break; 1515 } 1516 break; 1517 1518 case 'L': /* Insert n lines */ 1519 n = scp->term.param[0]; if (n < 1) n = 1; 1520 if (n > scp->ysize - scp->ypos) 1521 n = scp->ysize - scp->ypos; 1522 src = scp->crt_base + scp->ypos * scp->xsize; 1523 dst = src + n * scp->xsize; 1524 count = scp->ysize - (scp->ypos + n); 1525 move_up(src, dst, count * scp->xsize); 1526 fillw(scp->term.cur_attr | scr_map[0x20], src, 1527 n * scp->xsize); 1528 break; 1529 1530 case 'M': /* Delete n lines */ 1531 n = scp->term.param[0]; if (n < 1) n = 1; 1532 if (n > scp->ysize - scp->ypos) 1533 n = scp->ysize - scp->ypos; 1534 dst = scp->crt_base + scp->ypos * scp->xsize; 1535 src = dst + n * scp->xsize; 1536 count = scp->ysize - (scp->ypos + n); 1537 move_down(src, dst, count * scp->xsize); 1538 src = dst + count * scp->xsize; 1539 fillw(scp->term.cur_attr | scr_map[0x20], src, 1540 n * scp->xsize); 1541 break; 1542 1543 case 'P': /* Delete n chars */ 1544 n = scp->term.param[0]; if (n < 1) n = 1; 1545 if (n > scp->xsize - scp->xpos) 1546 n = scp->xsize - scp->xpos; 1547 dst = scp->crtat; 1548 src = dst + n; 1549 count = scp->xsize - (scp->xpos + n); 1550 move_down(src, dst, count); 1551 src = dst + count; 1552 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1553 break; 1554 1555 case '@': /* Insert n chars */ 1556 n = scp->term.param[0]; if (n < 1) n = 1; 1557 if (n > scp->xsize - scp->xpos) 1558 n = scp->xsize - scp->xpos; 1559 src = scp->crtat; 1560 dst = src + n; 1561 count = scp->xsize - (scp->xpos + n); 1562 move_up(src, dst, count); 1563 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1564 break; 1565 1566 case 'S': /* scroll up n lines */ 1567 n = scp->term.param[0]; if (n < 1) n = 1; 1568 bcopy(scp->crt_base + (scp->xsize * n), 1569 scp->crt_base, 1570 scp->xsize * (scp->ysize - n) * 1571 sizeof(u_short)); 1572 fillw(scp->term.cur_attr | scr_map[0x20], 1573 scp->crt_base + scp->xsize * 1574 (scp->ysize - 1), 1575 scp->xsize); 1576 break; 1577 1578 case 'T': /* scroll down n lines */ 1579 n = scp->term.param[0]; if (n < 1) n = 1; 1580 bcopy(scp->crt_base, 1581 scp->crt_base + (scp->xsize * n), 1582 scp->xsize * (scp->ysize - n) * 1583 sizeof(u_short)); 1584 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1585 scp->xsize); 1586 break; 1587 1588 case 'X': /* delete n characters in line */ 1589 n = scp->term.param[0]; if (n < 1) n = 1; 1590 fillw(scp->term.cur_attr | scr_map[0x20], 1591 scp->crt_base + scp->xpos + 1592 ((scp->xsize*scp->ypos) * sizeof(u_short)), n); 1593 break; 1594 1595 case 'Z': /* move n tabs backwards */ 1596 n = scp->term.param[0]; if (n < 1) n = 1; 1597 if ((i = scp->xpos & 0xf8) == scp->xpos) 1598 i -= 8*n; 1599 else 1600 i -= 8*(n-1); 1601 if (i < 0) 1602 i = 0; 1603 move_crsr(scp, i, scp->ypos); 1604 break; 1605 1606 case '`': /* move cursor to column n */ 1607 n = scp->term.param[0]; if (n < 1) n = 1; 1608 move_crsr(scp, n, scp->ypos); 1609 break; 1610 1611 case 'a': /* move cursor n columns to the right */ 1612 n = scp->term.param[0]; if (n < 1) n = 1; 1613 move_crsr(scp, scp->xpos + n, scp->ypos); 1614 break; 1615 1616 case 'd': /* move cursor to row n */ 1617 n = scp->term.param[0]; if (n < 1) n = 1; 1618 move_crsr(scp, scp->xpos, n); 1619 break; 1620 1621 case 'e': /* move cursor n rows down */ 1622 n = scp->term.param[0]; if (n < 1) n = 1; 1623 move_crsr(scp, scp->xpos, scp->ypos + n); 1624 break; 1625 1626 case 'm': /* change attribute */ 1627 if (scp->term.num_param == 0) 1628 n = 0; 1629 else 1630 n = scp->term.param[0]; 1631 switch (n) { 1632 case 0: /* back to normal */ 1633 scp->term.cur_attr = scp->term.std_attr; 1634 break; 1635 case 1: /* highlight (bold) */ 1636 scp->term.cur_attr &= 0xFF00; 1637 scp->term.cur_attr |= 0x0800; 1638 break; 1639 case 4: /* highlight (underline) */ 1640 scp->term.cur_attr &= 0x0F00; 1641 scp->term.cur_attr |= 0x0800; 1642 break; 1643 case 5: /* blink */ 1644 scp->term.cur_attr &= 0xFF00; 1645 scp->term.cur_attr |= 0x8000; 1646 break; 1647 case 7: /* reverse video */ 1648 scp->term.cur_attr = scp->term.rev_attr; 1649 break; 1650 case 30: case 31: case 32: case 33: /* set fg color */ 1651 case 34: case 35: case 36: case 37: 1652 scp->term.cur_attr = (scp->term.cur_attr & 0xF0FF) 1653 | (ansi_col[(n - 30) & 7] << 8); 1654 break; 1655 case 40: case 41: case 42: case 43: /* set bg color */ 1656 case 44: case 45: case 46: case 47: 1657 scp->term.cur_attr = (scp->term.cur_attr & 0x0FFF) 1658 | (ansi_col[(n - 40) & 7] << 12); 1659 break; 1660 } 1661 break; 1662 1663 case 'x': 1664 if (scp->term.num_param == 0) 1665 n = 0; 1666 else 1667 n = scp->term.param[0]; 1668 switch (n) { 1669 case 0: /* reset attributes */ 1670 scp->term.cur_attr = scp->term.std_attr = 1671 current_default->std_attr; 1672 scp->term.rev_attr = current_default->rev_attr; 1673 break; 1674 case 1: /* set ansi background */ 1675 scp->term.cur_attr = scp->term.std_attr = 1676 (scp->term.std_attr & 0x0F00) | 1677 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1678 break; 1679 case 2: /* set ansi foreground */ 1680 scp->term.cur_attr = scp->term.std_attr = 1681 (scp->term.std_attr & 0xF000) | 1682 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1683 break; 1684 case 3: /* set ansi attribute directly */ 1685 scp->term.cur_attr = scp->term.std_attr = 1686 (scp->term.param[1]&0xFF)<<8; 1687 break; 1688 case 5: /* set ansi reverse video background */ 1689 scp->term.rev_attr = 1690 (scp->term.rev_attr & 0x0F00) | 1691 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1692 break; 1693 case 6: /* set ansi reverse video foreground */ 1694 scp->term.rev_attr = 1695 (scp->term.rev_attr & 0xF000) | 1696 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1697 break; 1698 case 7: /* set ansi reverse video directly */ 1699 scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8; 1700 break; 1701 } 1702 break; 1703 1704 case 'z': /* switch to (virtual) console n */ 1705 if (scp->term.num_param == 1) 1706 switch_scr(scp->term.param[0]); 1707 break; 1708 } 1709 } 1710 else if (scp->term.esc == 3) { 1711 if (c >= '0' && c <= '9') { 1712 if (scp->term.num_param < MAX_ESC_PAR) { 1713 if (scp->term.last_param != scp->term.num_param) { 1714 scp->term.last_param = scp->term.num_param; 1715 scp->term.param[scp->term.num_param] = 0; 1716 } 1717 else 1718 scp->term.param[scp->term.num_param] *= 10; 1719 scp->term.param[scp->term.num_param] += c - '0'; 1720 return; 1721 } 1722 } 1723 scp->term.num_param = scp->term.last_param + 1; 1724 switch (c) { 1725 1726 case ';': 1727 if (scp->term.num_param < MAX_ESC_PAR) 1728 return; 1729 break; 1730 1731 case 'A': /* set display border color */ 1732 if (scp->term.num_param == 1) 1733 scp->border=scp->term.param[0] & 0xff; 1734 if (scp == cur_console) 1735 set_border(scp->border); 1736 break; 1737 1738 case 'B': /* set bell pitch and duration */ 1739 if (scp->term.num_param == 2) { 1740 scp->bell_pitch = scp->term.param[0]; 1741 scp->bell_duration = scp->term.param[1]*10; 1742 } 1743 break; 1744 1745 case 'C': /* set cursor shape (start & end line) */ 1746 if (scp->term.num_param == 2) { 1747 scp->cursor_start = scp->term.param[0] & 0x1F; 1748 scp->cursor_end = scp->term.param[1] & 0x1F; 1749 if (scp == cur_console) 1750 cursor_shape(scp->cursor_start, 1751 scp->cursor_end); 1752 } 1753 break; 1754 1755 case 'F': /* set ansi foreground */ 1756 if (scp->term.num_param == 1) 1757 scp->term.cur_attr = scp->term.std_attr = 1758 (scp->term.std_attr & 0xF000) 1759 | ((scp->term.param[0] & 0x0F) << 8); 1760 break; 1761 1762 case 'G': /* set ansi background */ 1763 if (scp->term.num_param == 1) 1764 scp->term.cur_attr = scp->term.std_attr = 1765 (scp->term.std_attr & 0x0F00) 1766 | ((scp->term.param[0] & 0x0F) << 12); 1767 break; 1768 1769 case 'H': /* set ansi reverse video foreground */ 1770 if (scp->term.num_param == 1) 1771 scp->term.rev_attr = 1772 (scp->term.rev_attr & 0xF000) 1773 | ((scp->term.param[0] & 0x0F) << 8); 1774 break; 1775 1776 case 'I': /* set ansi reverse video background */ 1777 if (scp->term.num_param == 1) 1778 scp->term.rev_attr = 1779 (scp->term.rev_attr & 0x0F00) 1780 | ((scp->term.param[0] & 0x0F) << 12); 1781 break; 1782 } 1783 } 1784 scp->term.esc = 0; 1785} 1786 1787 1788static void ansi_put(scr_stat *scp, u_char c) 1789{ 1790 if (scp->status & UNKNOWN_MODE) 1791 return; 1792 1793#if defined(STAR_SAVER) 1794 /* make screensaver happy */ 1795 if (scp == cur_console) { 1796 scrn_time_stamp = time.tv_sec; 1797 if (scrn_blanked) 1798 scrn_saver(0); 1799 } 1800#endif 1801 in_putc++; 1802 if (scp->term.esc) 1803 scan_esc(scp, c); 1804 else switch(c) { 1805 case 0x1B: /* start escape sequence */ 1806 scp->term.esc = 1; 1807 scp->term.num_param = 0; 1808 break; 1809 case 0x07: 1810 if (scp == cur_console) 1811 sysbeep(scp->bell_pitch, scp->bell_duration); 1812 break; 1813 case '\t': /* non-destructive tab */ 1814 scp->crtat += (8 - scp->xpos % 8); 1815 scp->xpos += (8 - scp->xpos % 8); 1816 break; 1817 case '\b': /* non-destructive backspace */ 1818 if (scp->crtat > scp->crt_base) { 1819 scp->crtat--; 1820 if (scp->xpos > 0) 1821 scp->xpos--; 1822 else { 1823 scp->xpos += scp->xsize - 1; 1824 scp->ypos--; 1825 } 1826 } 1827 break; 1828 case '\r': /* return to pos 0 */ 1829 move_crsr(scp, 0, scp->ypos); 1830 break; 1831 case '\n': /* newline, same pos */ 1832 scp->crtat += scp->xsize; 1833 scp->ypos++; 1834 break; 1835 case '\f': /* form feed, clears screen */ 1836 clear_screen(scp); 1837 break; 1838 default: 1839 /* Print only printables */ 1840 *scp->crtat = (scp->term.cur_attr | scr_map[c]); 1841 scp->crtat++; 1842 if (++scp->xpos >= scp->xsize) { 1843 scp->xpos = 0; 1844 scp->ypos++; 1845 } 1846 break; 1847 } 1848 if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) { 1849 bcopy(scp->crt_base + scp->xsize, scp->crt_base, 1850 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 1851 fillw(scp->term.cur_attr | scr_map[0x20], 1852 scp->crt_base + scp->xsize * (scp->ysize - 1), 1853 scp->xsize); 1854 scp->crtat -= scp->xsize; 1855 scp->ypos--; 1856 } 1857 in_putc--; 1858 if (delayed_next_scr) 1859 switch_scr(delayed_next_scr - 1); 1860} 1861 1862static void scinit(void) 1863{ 1864 u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was; 1865 unsigned cursorat; 1866 int i; 1867 1868 /* 1869 * catch that once in a blue moon occurence when scinit is called 1870 * TWICE, adding the CGA_BUF offset again -> poooff 1871 */ 1872 if (crtat != 0) 1873 return; 1874 /* 1875 * Crtat initialized to point to MONO buffer, if not present change 1876 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds 1877 * in the remapped offset at the "right" time 1878 */ 1879 was = *cp; 1880 *cp = (u_short) 0xA55A; 1881 if (*cp != 0xA55A) { 1882 crtc_addr = MONO_BASE; 1883 } else { 1884 *cp = was; 1885 crtc_addr = COLOR_BASE; 1886 Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short); 1887 } 1888 1889 /* Extract cursor location */ 1890 outb(crtc_addr,14); 1891 cursorat = inb(crtc_addr+1)<<8 ; 1892 outb(crtc_addr,15); 1893 cursorat |= inb(crtc_addr+1); 1894 crtat = Crtat + cursorat; 1895 1896 /* is this a VGA or higher ? */ 1897 outb(crtc_addr, 7); 1898 if (inb(crtc_addr) == 7) 1899 crtc_vga = 1; 1900 1901 current_default = &user_default; 1902 console[0].crtat = crtat; 1903 console[0].crt_base = Crtat; 1904 console[0].term.esc = 0; 1905 console[0].term.std_attr = current_default->std_attr; 1906 console[0].term.rev_attr = current_default->rev_attr; 1907 console[0].term.cur_attr = current_default->std_attr; 1908 console[0].xpos = cursorat % COL; 1909 console[0].ypos = cursorat / COL; 1910 console[0].border = BG_BLACK;; 1911 console[0].xsize = COL; 1912 console[0].ysize = ROW; 1913 console[0].status = 0; 1914 console[0].pid = 0; 1915 console[0].proc = NULL; 1916 console[0].smode.mode = VT_AUTO; 1917 console[0].bell_pitch = BELL_PITCH; 1918 console[0].bell_duration = BELL_DURATION; 1919 kernel_console.esc = 0; 1920 kernel_console.std_attr = kernel_default.std_attr; 1921 kernel_console.rev_attr = kernel_default.rev_attr; 1922 kernel_console.cur_attr = kernel_default.std_attr; 1923 /* initialize mapscrn array to a one to one map */ 1924 for (i=0; i<sizeof(scr_map); i++) 1925 scr_map[i] = i; 1926 clear_screen(&console[0]); 1927} 1928 1929 1930static void scput(u_char c) 1931{ 1932 scr_stat *scp = &console[0]; 1933 term_stat save; 1934 1935 if (crtat == 0) 1936 scinit(); 1937 save = scp->term; 1938 scp->term = kernel_console; 1939 current_default = &kernel_default; 1940 ansi_put(scp, c); 1941 kernel_console = scp->term; 1942 current_default = &user_default; 1943 scp->term = save; 1944} 1945 1946 1947static u_char *get_fstr(u_int c, u_int *len) 1948{ 1949 u_int i; 1950 1951 if (!(c & FKEY)) 1952 return(NULL); 1953 i = (c & 0xFF) - F_FN; 1954 if (i > n_fkey_tab) 1955 return(NULL); 1956 *len = fkey_tab[i].len; 1957 return(fkey_tab[i].str); 1958} 1959 1960 1961static void update_leds(int which) 1962{ 1963 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 1964 1965 kbd_cmd2(KB_SETLEDS, xlate_leds[which & LED_MASK]); 1966} 1967 1968 1969/* 1970 * scgetc(noblock) : get a character from the keyboard. 1971 * If noblock = 0 wait until a key is gotten. Otherwise return NOKEY. 1972 */ 1973u_int scgetc(int noblock) 1974{ 1975 u_char val, code, release; 1976 u_int state, action; 1977 struct key_t *key; 1978 static u_char esc_flag = 0, compose = 0; 1979 static u_int chr = 0; 1980 1981next_code: 1982 kbd_wait(); 1983 /* First see if there is something in the keyboard port */ 1984 if (inb(KB_STAT) & KB_BUF_FULL) 1985 val = inb(KB_DATA); 1986 else if (noblock) 1987 return(NOKEY); 1988 else 1989 goto next_code; 1990 1991 if (cur_console->status & KBD_RAW_MODE) 1992 return val; 1993 1994 code = val & 0x7F; 1995 release = val & 0x80; 1996 1997 switch (esc_flag) { 1998 case 0x00: /* normal scancode */ 1999 switch(code) { 2000 case 0x38: /* left alt (compose key) */ 2001 if (release && compose) { 2002 compose = 0; 2003 if (chr > 255) { 2004 sysbeep(BELL_PITCH, BELL_DURATION); 2005 chr = 0; 2006 } 2007 } 2008 else { 2009 if (!compose) { 2010 compose = 1; 2011 chr = 0; 2012 } 2013 } 2014 break; 2015 case 0x60: 2016 case 0x61: 2017 esc_flag = code; 2018 goto next_code; 2019 } 2020 break; 2021 case 0x60: /* 0xE0 prefix */ 2022 esc_flag = 0; 2023 switch (code) { 2024 case 0x1c: /* right enter key */ 2025 code = 0x59; 2026 break; 2027 case 0x1d: /* right ctrl key */ 2028 code = 0x5a; 2029 break; 2030 case 0x35: /* keypad divide key */ 2031 code = 0x5b; 2032 break; 2033 case 0x37: /* print scrn key */ 2034 code = 0x5c; 2035 break; 2036 case 0x38: /* right alt key (alt gr) */ 2037 code = 0x5d; 2038 break; 2039 case 0x47: /* grey home key */ 2040 code = 0x5e; 2041 break; 2042 case 0x48: /* grey up arrow key */ 2043 code = 0x5f; 2044 break; 2045 case 0x49: /* grey page up key */ 2046 code = 0x60; 2047 break; 2048 case 0x4b: /* grey left arrow key */ 2049 code = 0x61; 2050 break; 2051 case 0x4d: /* grey right arrow key */ 2052 code = 0x62; 2053 break; 2054 case 0x4f: /* grey end key */ 2055 code = 0x63; 2056 break; 2057 case 0x50: /* grey down arrow key */ 2058 code = 0x64; 2059 break; 2060 case 0x51: /* grey page down key */ 2061 code = 0x65; 2062 break; 2063 case 0x52: /* grey insert key */ 2064 code = 0x66; 2065 break; 2066 case 0x53: /* grey delete key */ 2067 code = 0x67; 2068 break; 2069 default: /* ignore everything else */ 2070 goto next_code; 2071 } 2072 break; 2073 case 0x61: /* 0xE1 prefix */ 2074 esc_flag = 0; 2075 if (code == 0x1D) 2076 esc_flag = 0x1D; 2077 goto next_code; 2078 /* NOT REACHED */ 2079 case 0x1D: /* pause / break */ 2080 esc_flag = 0; 2081 if (code != 0x45) 2082 goto next_code; 2083 code = 0x68; 2084 break; 2085 } 2086 2087 if (compose) { 2088 switch (code) { 2089 case 0x47: 2090 case 0x48: /* keypad 7,8,9 */ 2091 case 0x49: 2092 if (!release) 2093 chr = (code - 0x40) + chr*10; 2094 goto next_code; 2095 case 0x4b: 2096 case 0x4c: /* keypad 4,5,6 */ 2097 case 0x4d: 2098 if (!release) 2099 chr = (code - 0x47) + chr*10; 2100 goto next_code; 2101 case 0x4f: 2102 case 0x50: /* keypad 1,2,3 */ 2103 case 0x51: 2104 if (!release) 2105 chr = (code - 0x4e) + chr*10; 2106 goto next_code; 2107 case 0x52: /* keypad 0 */ 2108 if (!release) 2109 chr *= 10; 2110 goto next_code; 2111 case 0x38: /* left alt key */ 2112 break; 2113 default: 2114 if (chr) { 2115 compose = chr = 0; 2116 sysbeep(BELL_PITCH, BELL_DURATION); 2117 goto next_code; 2118 } 2119 break; 2120 } 2121 } 2122 2123 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2124 if ((!agrs && (cur_console->status & ALKED)) 2125 || (agrs && !(cur_console->status & ALKED))) 2126 code += ALTGR_OFFSET; 2127 key = &key_map.key[code]; 2128 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2129 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2130 state ^= 1; 2131 2132 /* Check for make/break */ 2133 action = key->map[state]; 2134 if (release) { /* key released */ 2135 if (key->spcl & 0x80) { 2136 switch (action) { 2137 case LSH: 2138 shfts &= ~1; 2139 break; 2140 case RSH: 2141 shfts &= ~2; 2142 break; 2143 case LCTR: 2144 ctls &= ~1; 2145 break; 2146 case RCTR: 2147 ctls &= ~2; 2148 break; 2149 case LALT: 2150 alts &= ~1; 2151 break; 2152 case RALT: 2153 alts &= ~2; 2154 break; 2155 case NLK: 2156 nlkcnt = 0; 2157 break; 2158 case CLK: 2159 clkcnt = 0; 2160 break; 2161 case SLK: 2162 slkcnt = 0; 2163 break; 2164 case ASH: 2165 agrs = 0; 2166 break; 2167 case ALK: 2168 alkcnt = 0; 2169 break; 2170 case META: 2171 metas = 0; 2172 break; 2173 } 2174 } 2175 if (chr && !compose) { 2176 action = chr; 2177 chr = 0; 2178 return(action); 2179 } 2180 } else { 2181 /* key pressed */ 2182 if (key->spcl & (0x80>>state)) { 2183 switch (action) { 2184 /* LOCKING KEYS */ 2185 case NLK: 2186 if (!nlkcnt) { 2187 nlkcnt++; 2188 if (cur_console->status & NLKED) 2189 cur_console->status &= ~NLKED; 2190 else 2191 cur_console->status |= NLKED; 2192 update_leds(cur_console->status & LED_MASK); 2193 } 2194 break; 2195 case CLK: 2196 if (!clkcnt) { 2197 clkcnt++; 2198 if (cur_console->status & CLKED) 2199 cur_console->status &= ~CLKED; 2200 else 2201 cur_console->status |= CLKED; 2202 update_leds(cur_console->status & LED_MASK); 2203 } 2204 break; 2205 case SLK: 2206 if (!slkcnt) { 2207 slkcnt++; 2208 if (cur_console->status & SLKED) { 2209 cur_console->status &= ~SLKED; 2210 pcstart(VIRTUAL_TTY(get_scr_num())); 2211 } 2212 else 2213 cur_console->status |= SLKED; 2214 update_leds(cur_console->status & LED_MASK); 2215 } 2216 break; 2217 case ALK: 2218 if (!alkcnt) { 2219 alkcnt++; 2220 if (cur_console->status & ALKED) 2221 cur_console->status &= ~ALKED; 2222 else 2223 cur_console->status |= ALKED; 2224 } 2225 break; 2226 2227 /* NON-LOCKING KEYS */ 2228 case NOP: 2229 break; 2230 case RBT: 2231#if defined(__FreeBSD__) 2232 shutdown_nice(); 2233#else 2234 cpu_reset(); 2235#endif 2236 break; 2237 case DBG: 2238#if DDB > 0 /* try to switch to console 0 */ 2239 if (cur_console->smode.mode == VT_AUTO && 2240 console[0].smode.mode == VT_AUTO) 2241 switch_scr(0); 2242 Debugger(); 2243 return(NOKEY); 2244#else 2245 printf("No debugger in kernel\n"); 2246#endif 2247 break; 2248 case LSH: 2249 shfts |= 1; 2250 break; 2251 case RSH: 2252 shfts |= 2; 2253 break; 2254 case LCTR: 2255 ctls |= 1; 2256 break; 2257 case RCTR: 2258 ctls |= 2; 2259 break; 2260 case LALT: 2261 alts |= 1; 2262 break; 2263 case RALT: 2264 alts |= 2; 2265 break; 2266 case ASH: 2267 agrs = 1; 2268 break; 2269 case META: 2270 metas = 1; 2271 break; 2272 case NEXT: 2273 switch_scr((get_scr_num()+1)%NCONS); 2274 break; 2275 default: 2276 if (action >= F_SCR && action <= L_SCR) { 2277 switch_scr(action - F_SCR); 2278 break; 2279 } 2280 if (action >= F_FN && action <= L_FN) 2281 action |= FKEY; 2282 return(action); 2283 } 2284 } 2285 else { 2286 if (metas) 2287 action |= MKEY; 2288 return(action); 2289 } 2290 } 2291 goto next_code; 2292} 2293 2294 2295int getchar(void) 2296{ 2297 u_char thechar; 2298 int s; 2299 2300 polling = 1; 2301 s = splhigh(); 2302 scput('>'); 2303 thechar = (u_char) scgetc(0); 2304 polling = 0; 2305 splx(s); 2306 switch (thechar) { 2307 default: 2308 if (thechar >= scr_map[0x20]) 2309 scput(thechar); 2310 return(thechar); 2311 case cr: 2312 case lf: 2313 scput(cr); scput(lf); 2314 return(lf); 2315 case bs: 2316 case del: 2317 scput(bs); scput(scr_map[0x20]); scput(bs); 2318 return(thechar); 2319 case cntld: 2320 scput('^'); scput('D'); scput('\r'); scput('\n'); 2321 return(0); 2322 } 2323} 2324 2325 2326u_int sgetc(int noblock) 2327{ 2328 return (scgetc(noblock & 0xff); 2329} 2330 2331int pcmmap(dev_t dev, int offset, int nprot) 2332{ 2333 if (offset > 0x20000) 2334 return EINVAL; 2335 return i386_btop((VIDEOMEM + offset)); 2336} 2337 2338 2339static void kbd_wait(void) 2340{ 2341 int i; 2342 2343 for (i=0; i<1000; i++) { /* up to 10 msec */ 2344 if ((inb(KB_STAT) & KB_READY) == 0) 2345 break; 2346 DELAY (10); 2347 } 2348} 2349 2350 2351static void kbd_cmd(u_char command) 2352{ 2353 kbd_wait(); 2354 outb(KB_DATA, command); 2355} 2356 2357 2358static void kbd_cmd2(u_char command, u_char arg) 2359{ 2360 int r, s = spltty(); 2361 do { 2362 kbd_cmd(command); 2363 r = kbd_reply(); 2364 if (r == KB_ACK) { 2365 kbd_cmd(arg & 0x7f); 2366 r = kbd_reply(); 2367 } 2368 } while (r != KB_ACK); 2369 splx(s); 2370} 2371 2372 2373static int kbd_reply() 2374{ 2375 int i; 2376 2377 kbd_wait(); 2378 for (i=0; i<50000; i++) { /* at least 300 msec, 500 msec enough */ 2379 if (inb(KB_STAT) & KB_BUF_FULL) 2380 return ((u_char) inb(KB_DATA)); 2381 DELAY (10); 2382 } 2383 return(-1); 2384} 2385 2386 2387static void set_mode(scr_stat *scp) 2388{ 2389 u_char byte; 2390 int s; 2391 2392 if (scp != cur_console) 2393 return; 2394 2395 /* (re)activate cursor */ 2396 untimeout((timeout_t)cursor_pos, 0); 2397 cursor_pos(1); 2398 2399 /* change cursor type if set */ 2400 if (scp->cursor_start != -1 && scp->cursor_end != -1) 2401 cursor_shape(scp->cursor_start, scp->cursor_end); 2402 2403 /* mode change only on VGA's */ 2404 if (!crtc_vga) 2405 return; 2406 2407 /* setup video hardware for the given mode */ 2408 s = splhigh(); 2409 switch(scp->mode) { 2410 case TEXT80x25: 2411 outb(crtc_addr, 9); byte = inb(crtc_addr+1); 2412 outb(crtc_addr, 9); outb(crtc_addr+1, byte | 0x0F); 2413 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* select font 0 */ 2414 break; 2415 case TEXT80x50: 2416 outb(crtc_addr, 9); byte = inb(crtc_addr+1); 2417 outb(crtc_addr, 9); outb(crtc_addr+1, (byte & 0xF0) | 0x07); 2418 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* select font 1 */ 2419 break; 2420 default: 2421 break; 2422 } 2423 splx(s); 2424 2425 /* set border color for this (virtual) console */ 2426 set_border(scp->border); 2427 return; 2428} 2429 2430 2431static void set_border(int color) 2432{ 2433 inb(crtc_addr+6); /* reset flip-flop */ 2434 outb(ATC, 0x11); outb(ATC, color); 2435 inb(crtc_addr+6); /* reset flip-flop */ 2436 outb(ATC, 0x20); /* enable Palette */ 2437} 2438 2439static void load_font(int segment, int size, char* font) 2440{ 2441 int ch, line, s; 2442 u_char val; 2443 2444 outb(TSIDX, 0x01); val = inb(TSREG); /* blank screen */ 2445 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 2446 2447 /* setup vga for loading fonts (graphics plane mode) */ 2448 s = splhigh(); 2449 inb(crtc_addr+6); /* reset flip/flop */ 2450 outb(ATC, 0x30); outb(ATC, 0x01); 2451 outb(TSIDX, 0x02); outb(TSREG, 0x04); 2452 outb(TSIDX, 0x04); outb(TSREG, 0x06); 2453 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 2454 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 2455 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); /* addr = a0000, 64kb */ 2456 splx(s); 2457 for (ch=0; ch < 256; ch++) 2458 for (line=0; line < size; line++) 2459 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line) = 2460 font[(ch*size)+line]; 2461 /* setup vga for text mode again */ 2462 s = splhigh(); 2463 inb(crtc_addr+6); /* reset flip/flop */ 2464 outb(ATC, 0x30); outb(ATC, 0x0C); 2465 outb(TSIDX, 0x02); outb(TSREG, 0x03); 2466 outb(TSIDX, 0x04); outb(TSREG, 0x02); 2467 outb(GDCIDX, 0x04); outb(GDCREG, 0x00); 2468 outb(GDCIDX, 0x05); outb(GDCREG, 0x10); 2469 if (crtc_addr == MONO_BASE) { 2470 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */ 2471 } 2472 else { 2473 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */ 2474 } 2475 splx(s); 2476 outb(TSIDX, 0x01); val = inb(TSREG); /* unblank screen */ 2477 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 2478} 2479 2480 2481static void load_palette(void) 2482{ 2483 int i; 2484 2485 outb(PIXMASK, 0xFF); /* no pixelmask */ 2486 outb(PALWADR, 0x00); 2487 for (i=0x00; i<0x300; i++) 2488 outb(PALDATA, palette[i]); 2489 inb(crtc_addr+6); /* reset flip/flop */ 2490 outb(ATC, 0x20); /* enable palette */ 2491} 2492 2493static void save_palette(void) 2494{ 2495 int i; 2496 2497 outb(PALRADR, 0x00); 2498 for (i=0x00; i<0x300; i++) 2499 palette[i] = inb(PALDATA); 2500 inb(crtc_addr+6); /* reset flip/flop */ 2501} 2502 2503 2504static void change_winsize(struct tty *tp, int x, int y) 2505{ 2506 if (tp->t_winsize.ws_col != x || tp->t_winsize.ws_row != y) { 2507 tp->t_winsize.ws_col = x; 2508 tp->t_winsize.ws_row = y; 2509 pgsignal(tp->t_pgrp, SIGWINCH, 1); 2510 } 2511} 2512 2513#endif /* NSC */ 2514