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