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