syscons.c revision 5160
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.81 1994/12/06 19:32:00 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 if (*(int*)data) { 934 sysbeep((*(int*)data)&0xffff, 935 (((*(int*)data)>>16)&0xffff)*hz/1000); 936 } 937 else { 938 sysbeep(scp->bell_pitch, scp->bell_duration); 939 } 940 return 0; 941 942 case KIOCSOUND: /* make tone (*data) hz */ 943 if (scp == cur_console) { 944 if (*(int*)data) { 945 int pitch = TIMER_FREQ/(*(int*)data); 946 /* set command for counter 2, 2 byte write */ 947 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) { 948 return EBUSY; 949 } 950 /* set pitch */ 951 outb(TIMER_CNTR2, pitch); 952 outb(TIMER_CNTR2, (pitch>>8)); 953 /* enable counter 2 output to speaker */ 954 outb(IO_PPI, inb(IO_PPI) | 3); 955 } 956 else { 957 /* disable counter 2 output to speaker */ 958 outb(IO_PPI, inb(IO_PPI) & 0xFC); 959 release_timer2(); 960 } 961 } 962 return 0; 963 964 case KDGKBTYPE: /* get keyboard type */ 965 *data = 0; /* type not known (yet) */ 966 return 0; 967 968 case KDSETLED: /* set keyboard LED status */ 969 if (*data >= 0 && *data <= LED_MASK) { 970 scp->status &= ~LED_MASK; 971 scp->status |= *data; 972 if (scp == cur_console) 973 update_leds(scp->status); 974 return 0; 975 } 976 return EINVAL; 977 978 case KDGETLED: /* get keyboard LED status */ 979 *data = scp->status & LED_MASK; 980 return 0; 981 982 case GETFKEY: /* get functionkey string */ 983 if (*(u_short*)data < n_fkey_tab) { 984 fkeyarg_t *ptr = (fkeyarg_t*)data; 985 bcopy(&fkey_tab[ptr->keynum].str, 986 ptr->keydef, 987 fkey_tab[ptr->keynum].len); 988 ptr->flen = fkey_tab[ptr->keynum].len; 989 return 0; 990 } 991 else 992 return EINVAL; 993 994 case SETFKEY: /* set functionkey string */ 995 if (*(u_short*)data < n_fkey_tab) { 996 fkeyarg_t *ptr = (fkeyarg_t*)data; 997 bcopy(ptr->keydef, 998 &fkey_tab[ptr->keynum].str, 999 min(ptr->flen, MAXFK)); 1000 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1001 return 0; 1002 } 1003 else 1004 return EINVAL; 1005 1006 case GIO_SCRNMAP: /* get output translation table */ 1007 bcopy(&scr_map, data, sizeof(scr_map)); 1008 return 0; 1009 1010 case PIO_SCRNMAP: /* set output translation table */ 1011 bcopy(data, &scr_map, sizeof(scr_map)); 1012 return 0; 1013 1014 case GIO_KEYMAP: /* get keyboard translation table */ 1015 bcopy(&key_map, data, sizeof(key_map)); 1016 return 0; 1017 1018 case PIO_KEYMAP: /* set keyboard translation table */ 1019 bcopy(data, &key_map, sizeof(key_map)); 1020 return 0; 1021 1022 case PIO_FONT8x8: /* set 8x8 dot font */ 1023 if (!crtc_vga) 1024 return ENXIO; 1025 bcopy(data, font_8, 8*256); 1026 fonts_loaded |= FONT_8_LOADED; 1027 copy_font(LOAD, 1, 8, font_8); 1028 return 0; 1029 1030 case GIO_FONT8x8: /* get 8x8 dot font */ 1031 if (!crtc_vga) 1032 return ENXIO; 1033 if (fonts_loaded & FONT_8_LOADED) { 1034 bcopy(font_8, data, 8*256); 1035 return 0; 1036 } 1037 else 1038 return ENXIO; 1039 1040 case PIO_FONT8x14: /* set 8x14 dot font */ 1041 if (!crtc_vga) 1042 return ENXIO; 1043 bcopy(data, font_14, 14*256); 1044 fonts_loaded |= FONT_14_LOADED; 1045 copy_font(LOAD, 2, 14, font_14); 1046 return 0; 1047 1048 case GIO_FONT8x14: /* get 8x14 dot font */ 1049 if (!crtc_vga) 1050 return ENXIO; 1051 if (fonts_loaded & FONT_14_LOADED) { 1052 bcopy(font_14, data, 14*256); 1053 return 0; 1054 } 1055 else 1056 return ENXIO; 1057 1058 case PIO_FONT8x16: /* set 8x16 dot font */ 1059 if (!crtc_vga) 1060 return ENXIO; 1061 bcopy(data, font_16, 16*256); 1062 fonts_loaded |= FONT_16_LOADED; 1063 copy_font(LOAD, 0, 16, font_16); 1064 return 0; 1065 1066 case GIO_FONT8x16: /* get 8x16 dot font */ 1067 if (!crtc_vga) 1068 return ENXIO; 1069 if (fonts_loaded & FONT_16_LOADED) { 1070 bcopy(font_16, data, 16*256); 1071 return 0; 1072 } 1073 else 1074 return ENXIO; 1075 1076 case CONSOLE_X_MODE_ON: /* just to be compatible */ 1077 if (saved_console < 0) { 1078 saved_console = get_scr_num(); 1079 switch_scr(minor(dev)); 1080 fp = (struct trapframe *)p->p_md.md_regs; 1081 fp->tf_eflags |= PSL_IOPL; 1082 scp->status |= UNKNOWN_MODE; 1083 scp->status |= KBD_RAW_MODE; 1084 return 0; 1085 } 1086 return EAGAIN; 1087 1088 case CONSOLE_X_MODE_OFF:/* just to be compatible */ 1089 fp = (struct trapframe *)p->p_md.md_regs; 1090 fp->tf_eflags &= ~PSL_IOPL; 1091 if (crtc_vga) { 1092 if (fonts_loaded & FONT_16_LOADED) 1093 copy_font(LOAD, 0, 16, font_16); 1094 if (fonts_loaded & FONT_8_LOADED) 1095 copy_font(LOAD, 1, 8, font_8); 1096 if (fonts_loaded & FONT_14_LOADED) 1097 copy_font(LOAD, 2, 14, font_14); 1098 load_palette(); 1099 } 1100 scp->status &= ~UNKNOWN_MODE; 1101 set_mode(scp); 1102 clear_screen(scp); 1103 scp->status &= ~KBD_RAW_MODE; 1104 switch_scr(saved_console); 1105 saved_console = -1; 1106 return 0; 1107 1108 case CONSOLE_X_BELL: /* more compatibility */ 1109 /* 1110 * if set, data is a pointer to a length 2 array of 1111 * integers. data[0] is the pitch in Hz and data[1] 1112 * is the duration in msec. 1113 */ 1114 if (data) 1115 sysbeep(TIMER_FREQ/((int*)data)[0], 1116 ((int*)data)[1]*hz/1000); 1117 else 1118 sysbeep(scp->bell_pitch, scp->bell_duration); 1119 return 0; 1120 1121 default: 1122 break; 1123 } 1124 1125 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1126 if (error >= 0) 1127 return(error); 1128 error = ttioctl(tp, cmd, data, flag); 1129 if (error >= 0) 1130 return(error); 1131 return(ENOTTY); 1132} 1133 1134void 1135pcxint(dev_t dev) 1136{ 1137 struct tty *tp = get_tty_ptr(dev); 1138 1139 if (!tp) 1140 return; 1141 tp->t_state &= ~TS_BUSY; 1142 if (tp->t_line) 1143 (*linesw[tp->t_line].l_start)(tp); 1144 else 1145 pcstart(tp); 1146} 1147 1148void 1149pcstart(struct tty *tp) 1150{ 1151 struct clist *rbp; 1152 int i, s, len; 1153 u_char buf[PCBURST]; 1154 scr_stat *scp = get_scr_stat(tp->t_dev); 1155 1156 if (scp->status & SLKED) 1157 return; 1158 s = spltty(); 1159 if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { 1160 tp->t_state |= TS_BUSY; 1161 splx(s); 1162 rbp = &tp->t_outq; 1163 while (rbp->c_cc) { 1164 len = q_to_b(rbp, buf, PCBURST); 1165 for (i=0; i<len; i++) 1166 if (buf[i]) ansi_put(scp, buf[i]); 1167 } 1168 s = spltty(); 1169 tp->t_state &= ~TS_BUSY; 1170#if 0 1171 if (rbp->c_cc) { 1172 tp->t_state |= TS_TIMEOUT; 1173 timeout((timeout_t)ttrstrt, (caddr_t)tp, 1); 1174 } 1175#endif 1176 if (rbp->c_cc <= tp->t_lowat) { 1177 if (tp->t_state & TS_ASLEEP) { 1178 tp->t_state &= ~TS_ASLEEP; 1179 wakeup((caddr_t)rbp); 1180 } 1181 selwakeup(&tp->t_wsel); 1182 } 1183 } 1184 splx(s); 1185} 1186 1187void 1188pccnprobe(struct consdev *cp) 1189{ 1190 int maj; 1191 1192 /* locate the major number */ 1193 for (maj = 0; maj < nchrdev; maj++) 1194 if ((void*)cdevsw[maj].d_open == (void*)pcopen) 1195 break; 1196 1197 /* initialize required fields */ 1198 cp->cn_dev = makedev(maj, NCONS); 1199 cp->cn_pri = CN_INTERNAL; 1200} 1201 1202void 1203pccninit(struct consdev *cp) 1204{ 1205 scinit(); 1206} 1207 1208void 1209pccnputc(dev_t dev, char c) 1210{ 1211 if (c == '\n') 1212 scput('\r'); 1213 scput(c); 1214 if (cur_console == &console[0]) { 1215 int pos = cur_console->crtat - cur_console->crt_base; 1216 if (pos != cur_cursor_pos) { 1217 cur_cursor_pos = pos; 1218 outb(crtc_addr,14); 1219 outb(crtc_addr+1,pos >> 8); 1220 outb(crtc_addr,15); 1221 outb(crtc_addr+1,pos&0xff); 1222 } 1223 } 1224} 1225 1226int 1227pccngetc(dev_t dev) 1228{ 1229 int s = spltty(); /* block scintr while we poll */ 1230 int c = scgetc(0); 1231 splx(s); 1232 return(c); 1233} 1234 1235int 1236pccncheckc(dev_t dev) 1237{ 1238 return (scgetc(1) & 0xff); 1239} 1240 1241static void 1242none_saver(int test) 1243{ 1244} 1245 1246static void 1247fade_saver(int test) 1248{ 1249 static int count = 0; 1250 int i; 1251 1252 if (test) { 1253 scrn_blanked = 1; 1254 if (count < 64) { 1255 outb(PIXMASK, 0xFF); /* no pixelmask */ 1256 outb(PALWADR, 0x00); 1257 outb(PALDATA, 0); 1258 outb(PALDATA, 0); 1259 outb(PALDATA, 0); 1260 for (i = 3; i < 768; i++) { 1261 if (palette[i] - count > 15) 1262 outb(PALDATA, palette[i]-count); 1263 else 1264 outb(PALDATA, 15); 1265 } 1266 inb(crtc_addr+6); /* reset flip/flop */ 1267 outb(ATC, 0x20); /* enable palette */ 1268 count++; 1269 } 1270 } 1271 else { 1272 count = scrn_blanked = 0; 1273 load_palette(); 1274 } 1275} 1276 1277static void 1278blank_saver(int test) 1279{ 1280 u_char val; 1281 if (test) { 1282 scrn_blanked = 1; 1283 outb(TSIDX, 0x01); val = inb(TSREG); 1284 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 1285 } 1286 else { 1287 scrn_blanked = 0; 1288 outb(TSIDX, 0x01); val = inb(TSREG); 1289 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 1290 } 1291} 1292 1293static void 1294green_saver(int test) 1295{ 1296 u_char val; 1297 if (test) { 1298 scrn_blanked = 1; 1299 outb(TSIDX, 0x01); val = inb(TSREG); 1300 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 1301 outb(crtc_addr, 0x17); val = inb(crtc_addr + 1); 1302 outb(crtc_addr + 1, val & ~0x80); 1303 } 1304 else { 1305 scrn_blanked = 0; 1306 outb(TSIDX, 0x01); val = inb(TSREG); 1307 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 1308 outb(crtc_addr, 0x17); val = inb(crtc_addr + 1); 1309 outb(crtc_addr + 1, val | 0x80); 1310 } 1311} 1312 1313#define NUM_STARS 50 1314 1315/* 1316 * Alternate saver that got its inspiration from a well known utility 1317 * package for an inferior^H^H^H^H^H^Hfamous OS. 1318 */ 1319static void 1320star_saver(int test) 1321{ 1322 scr_stat *scp = cur_console; 1323 int cell, i; 1324 char pattern[] = {"...........++++*** "}; 1325 char colors[] = {FG_DARKGREY, FG_LIGHTGREY, 1326 FG_WHITE, FG_LIGHTCYAN}; 1327 static u_short stars[NUM_STARS][2]; 1328 1329 if (test) { 1330 if (!scrn_blanked) { 1331 bcopy(Crtat, scp->scr_buf, 1332 scp->xsize * scp->ysize * 2); 1333 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat, 1334 scp->xsize * scp->ysize); 1335 set_border(0); 1336 i = scp->ysize * scp->xsize + 5; 1337 outb(crtc_addr, 14); 1338 outb(crtc_addr+1, i >> 8); 1339 outb(crtc_addr, 15); 1340 outb(crtc_addr+1, i & 0xff); 1341 scrn_blanked = 1; 1342 for(i=0; i<NUM_STARS; i++) { 1343 stars[i][0] = 1344 random() % (scp->xsize*scp->ysize); 1345 stars[i][1] = 0; 1346 } 1347 } 1348 cell = random() % NUM_STARS; 1349 *((u_short*)(Crtat + stars[cell][0])) = 1350 scr_map[pattern[stars[cell][1]]] | 1351 colors[random()%sizeof(colors)] << 8; 1352 if ((stars[cell][1]+=(random()%4)) >= sizeof(pattern)-1) { 1353 stars[cell][0] = random() % (scp->xsize*scp->ysize); 1354 stars[cell][1] = 0; 1355 } 1356 } 1357 else { 1358 if (scrn_blanked) { 1359 bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2); 1360 cur_cursor_pos = -1; 1361 set_border(scp->border); 1362 scrn_blanked = 0; 1363 } 1364 } 1365} 1366 1367static void 1368snake_saver(int test) 1369{ 1370 const char saves[] = {"FreeBSD-2.0"}; 1371 static u_char *savs[sizeof(saves)-1]; 1372 static int dirx, diry; 1373 int f; 1374 scr_stat *scp = cur_console; 1375 1376 if (test) { 1377 if (!scrn_blanked) { 1378 bcopy(Crtat, scp->scr_buf, 1379 scp->xsize * scp->ysize * 2); 1380 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], 1381 Crtat, scp->xsize * scp->ysize); 1382 set_border(0); 1383 dirx = (scp->xpos ? 1 : -1); 1384 diry = (scp->ypos ? 1385 scp->xsize : -scp->xsize); 1386 for (f=0; f< sizeof(saves)-1; f++) 1387 savs[f] = (u_char *)Crtat + 2 * 1388 (scp->xpos+scp->ypos*scp->xsize); 1389 *(savs[0]) = scr_map[*saves]; 1390 f = scp->ysize * scp->xsize + 5; 1391 outb(crtc_addr, 14); 1392 outb(crtc_addr+1, f >> 8); 1393 outb(crtc_addr, 15); 1394 outb(crtc_addr+1, f & 0xff); 1395 scrn_blanked = 1; 1396 } 1397 if (scrn_blanked++ < 4) 1398 return; 1399 scrn_blanked = 1; 1400 *(savs[sizeof(saves)-2]) = scr_map[0x20]; 1401 for (f=sizeof(saves)-2; f > 0; f--) 1402 savs[f] = savs[f-1]; 1403 f = (savs[0] - (u_char *)Crtat) / 2; 1404 if ((f % scp->xsize) == 0 || 1405 (f % scp->xsize) == scp->xsize - 1 || 1406 (random() % 50) == 0) 1407 dirx = -dirx; 1408 if ((f / scp->xsize) == 0 || 1409 (f / scp->xsize) == scp->ysize - 1 || 1410 (random() % 20) == 0) 1411 diry = -diry; 1412 savs[0] += 2*dirx + 2*diry; 1413 for (f=sizeof(saves)-2; f>=0; f--) 1414 *(savs[f]) = scr_map[saves[f]]; 1415 } 1416 else { 1417 if (scrn_blanked) { 1418 bcopy(scp->scr_buf, Crtat, 1419 scp->xsize * scp->ysize * 2); 1420 cur_cursor_pos = -1; 1421 set_border(scp->border); 1422 scrn_blanked = 0; 1423 } 1424 } 1425} 1426 1427static void 1428cursor_shape(int start, int end) 1429{ 1430 outb(crtc_addr, 10); 1431 outb(crtc_addr+1, start & 0xFF); 1432 outb(crtc_addr, 11); 1433 outb(crtc_addr+1, end & 0xFF); 1434} 1435 1436#if !defined(FAT_CURSOR) 1437static void 1438get_cursor_shape(int *start, int *end) 1439{ 1440 outb(crtc_addr, 10); 1441 *start = inb(crtc_addr+1) & 0x1F; 1442 outb(crtc_addr, 11); 1443 *end = inb(crtc_addr+1) & 0x1F; 1444} 1445#endif 1446 1447static void 1448cursor_pos(int force) 1449{ 1450 int pos; 1451 1452 if (cur_console->status & UNKNOWN_MODE) 1453 return; 1454 if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time)) 1455 SCRN_SAVER(1); 1456 pos = cur_console->crtat - cur_console->crt_base; 1457 if (force || (!scrn_blanked && pos != cur_cursor_pos)) { 1458 cur_cursor_pos = pos; 1459 outb(crtc_addr, 14); 1460 outb(crtc_addr+1, pos>>8); 1461 outb(crtc_addr, 15); 1462 outb(crtc_addr+1, pos&0xff); 1463 } 1464 timeout((timeout_t)cursor_pos, 0, hz/20); 1465} 1466 1467static void 1468clear_screen(scr_stat *scp) 1469{ 1470 move_crsr(scp, 0, 0); 1471 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1472 scp->xsize * scp->ysize); 1473} 1474 1475static int 1476switch_scr(u_int next_scr) 1477{ 1478 if (switch_in_progress && 1479 (cur_console->proc != pfind(cur_console->pid))) 1480 switch_in_progress = 0; 1481 1482 if (next_scr >= NCONS || switch_in_progress 1483 || (cur_console->smode.mode == VT_AUTO 1484 && cur_console->status & UNKNOWN_MODE)) { 1485 sysbeep(BELL_PITCH, BELL_DURATION); 1486 return EINVAL; 1487 } 1488 1489 /* is the wanted virtual console open ? */ 1490 if (next_scr) { 1491 struct tty *tp = VIRTUAL_TTY(next_scr); 1492 if (!(tp->t_state & TS_ISOPEN)) { 1493 sysbeep(BELL_PITCH, BELL_DURATION); 1494 return EINVAL; 1495 } 1496 } 1497 if (in_putc) { /* delay switch if in putc */ 1498 delayed_next_scr = next_scr+1; 1499 return 0; 1500 } 1501 switch_in_progress = 1; 1502 old_scp = cur_console; 1503 new_scp = &console[next_scr]; 1504 wakeup((caddr_t)&new_scp->smode); 1505 if (new_scp == old_scp) { 1506 switch_in_progress = 0; 1507 return 0; 1508 } 1509 1510 /* has controlling process died? */ 1511 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1512 old_scp->smode.mode = VT_AUTO; 1513 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1514 new_scp->smode.mode = VT_AUTO; 1515 1516 /* check the modes and switch approbiatly */ 1517 if (old_scp->smode.mode == VT_PROCESS) { 1518 old_scp->status |= SWITCH_WAIT_REL; 1519 psignal(old_scp->proc, old_scp->smode.relsig); 1520 } 1521 else { 1522 exchange_scr(); 1523 if (new_scp->smode.mode == VT_PROCESS) { 1524 new_scp->status |= SWITCH_WAIT_ACQ; 1525 psignal(new_scp->proc, new_scp->smode.acqsig); 1526 } 1527 else 1528 switch_in_progress = 0; 1529 } 1530 return 0; 1531} 1532 1533static void 1534exchange_scr(void) 1535{ 1536 bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2); 1537 old_scp->crt_base = old_scp->scr_buf; 1538 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1539 cur_console = new_scp; 1540 if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)) 1541 set_mode(new_scp); 1542 new_scp->crt_base = Crtat; 1543 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1544 bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2); 1545 update_leds(new_scp->status); 1546 if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) { 1547 if (fonts_loaded & FONT_16_LOADED) 1548 copy_font(LOAD, 0, 16, font_16); 1549 if (fonts_loaded & FONT_8_LOADED) 1550 copy_font(LOAD, 1, 8, font_8); 1551 if (fonts_loaded & FONT_14_LOADED) 1552 copy_font(LOAD, 2, 14, font_14); 1553 load_palette(); 1554 } 1555 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1556 shfts = ctls = alts = agrs = metas = 0; 1557 delayed_next_scr = 0; 1558} 1559 1560static void 1561move_crsr(scr_stat *scp, int x, int y) 1562{ 1563 if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize) 1564 return; 1565 scp->xpos = x; 1566 scp->ypos = y; 1567 scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos; 1568} 1569 1570static void 1571move_up(u_short *s, u_short *d, u_int len) 1572{ 1573 s += len; 1574 d += len; 1575 while (len-- > 0) 1576 *--d = *--s; 1577} 1578 1579static void 1580move_down(u_short *s, u_short *d, u_int len) 1581{ 1582 while (len-- > 0) 1583 *d++ = *s++; 1584} 1585 1586static void 1587scan_esc(scr_stat *scp, u_char c) 1588{ 1589 static u_char ansi_col[16] = 1590 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1591 int i, n; 1592 u_short *src, *dst, count; 1593 1594 if (scp->term.esc == 1) { 1595 switch (c) { 1596 1597 case '[': /* Start ESC [ sequence */ 1598 scp->term.esc = 2; 1599 scp->term.last_param = -1; 1600 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1601 scp->term.param[i] = 1; 1602 scp->term.num_param = 0; 1603 return; 1604 1605 case 'M': /* Move cursor up 1 line, scroll if at top */ 1606 if (scp->ypos > 0) 1607 move_crsr(scp, scp->xpos, scp->ypos - 1); 1608 else { 1609 move_up(scp->crt_base, 1610 scp->crt_base + scp->xsize, 1611 (scp->ysize - 1) * scp->xsize); 1612 fillw(scp->term.cur_attr | scr_map[0x20], 1613 scp->crt_base, scp->xsize); 1614 } 1615 break; 1616#if notyet 1617 case 'Q': 1618 scp->term.esc = 4; 1619 break; 1620#endif 1621 case 'c': /* Clear screen & home */ 1622 clear_screen(scp); 1623 break; 1624 } 1625 } 1626 else if (scp->term.esc == 2) { 1627 if (c >= '0' && c <= '9') { 1628 if (scp->term.num_param < MAX_ESC_PAR) { 1629 if (scp->term.last_param != scp->term.num_param) { 1630 scp->term.last_param = scp->term.num_param; 1631 scp->term.param[scp->term.num_param] = 0; 1632 } 1633 else 1634 scp->term.param[scp->term.num_param] *= 10; 1635 scp->term.param[scp->term.num_param] += c - '0'; 1636 return; 1637 } 1638 } 1639 scp->term.num_param = scp->term.last_param + 1; 1640 switch (c) { 1641 1642 case ';': 1643 if (scp->term.num_param < MAX_ESC_PAR) 1644 return; 1645 break; 1646 1647 case '=': 1648 scp->term.esc = 3; 1649 scp->term.last_param = -1; 1650 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1651 scp->term.param[i] = 1; 1652 scp->term.num_param = 0; 1653 return; 1654 1655 case 'A': /* up 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 'B': /* down n rows */ 1661 n = scp->term.param[0]; if (n < 1) n = 1; 1662 move_crsr(scp, scp->xpos, scp->ypos + n); 1663 break; 1664 1665 case 'C': /* right 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 'D': /* left n columns */ 1671 n = scp->term.param[0]; if (n < 1) n = 1; 1672 move_crsr(scp, scp->xpos - n, scp->ypos); 1673 break; 1674 1675 case 'E': /* cursor to start of line n lines down */ 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': /* cursor to start of line n lines up */ 1681 n = scp->term.param[0]; if (n < 1) n = 1; 1682 move_crsr(scp, 0, scp->ypos - n); 1683 break; 1684 1685 case 'f': /* System V consoles .. */ 1686 case 'H': /* Cursor move */ 1687 if (scp->term.num_param == 0) 1688 move_crsr(scp, 0, 0); 1689 else if (scp->term.num_param == 2) 1690 move_crsr(scp, scp->term.param[1] - 1, 1691 scp->term.param[0] - 1); 1692 break; 1693 1694 case 'J': /* Clear all or part of display */ 1695 if (scp->term.num_param == 0) 1696 n = 0; 1697 else 1698 n = scp->term.param[0]; 1699 switch (n) { 1700 case 0: /* clear form cursor to end of display */ 1701 fillw(scp->term.cur_attr | scr_map[0x20], 1702 scp->crtat, scp->crt_base + 1703 scp->xsize * scp->ysize - 1704 scp->crtat); 1705 break; 1706 case 1: /* clear from beginning of display to cursor */ 1707 fillw(scp->term.cur_attr | scr_map[0x20], 1708 scp->crt_base, 1709 scp->crtat - scp->crt_base); 1710 break; 1711 case 2: /* clear entire display */ 1712 clear_screen(scp); 1713 break; 1714 } 1715 break; 1716 1717 case 'K': /* Clear all or part of line */ 1718 if (scp->term.num_param == 0) 1719 n = 0; 1720 else 1721 n = scp->term.param[0]; 1722 switch (n) { 1723 case 0: /* clear form cursor to end of line */ 1724 fillw(scp->term.cur_attr | scr_map[0x20], 1725 scp->crtat, scp->xsize - scp->xpos); 1726 break; 1727 case 1: /* clear from beginning of line to cursor */ 1728 fillw(scp->term.cur_attr|scr_map[0x20], 1729 scp->crtat - (scp->xsize - scp->xpos), 1730 (scp->xsize - scp->xpos) + 1); 1731 break; 1732 case 2: /* clear entire line */ 1733 fillw(scp->term.cur_attr|scr_map[0x20], 1734 scp->crtat - (scp->xsize - scp->xpos), 1735 scp->xsize); 1736 break; 1737 } 1738 break; 1739 1740 case 'L': /* Insert n lines */ 1741 n = scp->term.param[0]; if (n < 1) n = 1; 1742 if (n > scp->ysize - scp->ypos) 1743 n = scp->ysize - scp->ypos; 1744 src = scp->crt_base + scp->ypos * scp->xsize; 1745 dst = src + n * scp->xsize; 1746 count = scp->ysize - (scp->ypos + n); 1747 move_up(src, dst, count * scp->xsize); 1748 fillw(scp->term.cur_attr | scr_map[0x20], src, 1749 n * scp->xsize); 1750 break; 1751 1752 case 'M': /* Delete n lines */ 1753 n = scp->term.param[0]; if (n < 1) n = 1; 1754 if (n > scp->ysize - scp->ypos) 1755 n = scp->ysize - scp->ypos; 1756 dst = scp->crt_base + scp->ypos * scp->xsize; 1757 src = dst + n * scp->xsize; 1758 count = scp->ysize - (scp->ypos + n); 1759 move_down(src, dst, count * scp->xsize); 1760 src = dst + count * scp->xsize; 1761 fillw(scp->term.cur_attr | scr_map[0x20], src, 1762 n * scp->xsize); 1763 break; 1764 1765 case 'P': /* Delete n chars */ 1766 n = scp->term.param[0]; if (n < 1) n = 1; 1767 if (n > scp->xsize - scp->xpos) 1768 n = scp->xsize - scp->xpos; 1769 dst = scp->crtat; 1770 src = dst + n; 1771 count = scp->xsize - (scp->xpos + n); 1772 move_down(src, dst, count); 1773 src = dst + count; 1774 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1775 break; 1776 1777 case '@': /* Insert n chars */ 1778 n = scp->term.param[0]; if (n < 1) n = 1; 1779 if (n > scp->xsize - scp->xpos) 1780 n = scp->xsize - scp->xpos; 1781 src = scp->crtat; 1782 dst = src + n; 1783 count = scp->xsize - (scp->xpos + n); 1784 move_up(src, dst, count); 1785 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1786 break; 1787 1788 case 'S': /* scroll up n lines */ 1789 n = scp->term.param[0]; if (n < 1) n = 1; 1790 if (n > scp->ysize) 1791 n = scp->ysize; 1792 bcopy(scp->crt_base + (scp->xsize * n), 1793 scp->crt_base, 1794 scp->xsize * (scp->ysize - n) * 1795 sizeof(u_short)); 1796 fillw(scp->term.cur_attr | scr_map[0x20], 1797 scp->crt_base + scp->xsize * 1798 (scp->ysize - n), 1799 scp->xsize * n); 1800 break; 1801 1802 case 'T': /* scroll down n lines */ 1803 n = scp->term.param[0]; if (n < 1) n = 1; 1804 if (n > scp->ysize) 1805 n = scp->ysize; 1806 bcopy(scp->crt_base, 1807 scp->crt_base + (scp->xsize * n), 1808 scp->xsize * (scp->ysize - n) * 1809 sizeof(u_short)); 1810 fillw(scp->term.cur_attr | scr_map[0x20], 1811 scp->crt_base, scp->xsize * n); 1812 break; 1813 1814 case 'X': /* delete n characters in line */ 1815 n = scp->term.param[0]; if (n < 1) n = 1; 1816 if (n > scp->xsize - scp->xpos) 1817 n = scp->xsize - scp->xpos; 1818 fillw(scp->term.cur_attr | scr_map[0x20], 1819 scp->crt_base + scp->xpos + 1820 ((scp->xsize*scp->ypos) * sizeof(u_short)), n); 1821 break; 1822 1823 case 'Z': /* move n tabs backwards */ 1824 n = scp->term.param[0]; if (n < 1) n = 1; 1825 if ((i = scp->xpos & 0xf8) == scp->xpos) 1826 i -= 8*n; 1827 else 1828 i -= 8*(n-1); 1829 if (i < 0) 1830 i = 0; 1831 move_crsr(scp, i, scp->ypos); 1832 break; 1833 1834 case '`': /* move cursor to column n */ 1835 n = scp->term.param[0]; if (n < 1) n = 1; 1836 move_crsr(scp, n, scp->ypos); 1837 break; 1838 1839 case 'a': /* move cursor n columns to the right */ 1840 n = scp->term.param[0]; if (n < 1) n = 1; 1841 move_crsr(scp, scp->xpos + n, scp->ypos); 1842 break; 1843 1844 case 'd': /* move cursor to row n */ 1845 n = scp->term.param[0]; if (n < 1) n = 1; 1846 move_crsr(scp, scp->xpos, n); 1847 break; 1848 1849 case 'e': /* move cursor n rows down */ 1850 n = scp->term.param[0]; if (n < 1) n = 1; 1851 move_crsr(scp, scp->xpos, scp->ypos + n); 1852 break; 1853 1854 case 'm': /* change attribute */ 1855 if (scp->term.num_param == 0) { 1856 scp->term.cur_attr = scp->term.std_attr; 1857 break; 1858 } 1859 for (i = 0; i < scp->term.num_param; i++) { 1860 switch (n = scp->term.param[i]) { 1861 case 0: /* back to normal */ 1862 scp->term.cur_attr = scp->term.std_attr; 1863 break; 1864 case 1: /* highlight (bold) */ 1865 scp->term.cur_attr &= 0xFF00; 1866 scp->term.cur_attr |= 0x0800; 1867 break; 1868 case 4: /* highlight (underline) */ 1869 scp->term.cur_attr &= 0xFF00; 1870 scp->term.cur_attr |= 0x0800; 1871 break; 1872 case 5: /* blink */ 1873 scp->term.cur_attr &= 0xFF00; 1874 scp->term.cur_attr |= 0x8000; 1875 break; 1876 case 7: /* reverse video */ 1877 scp->term.cur_attr = scp->term.rev_attr; 1878 break; 1879 case 30: case 31: /* set fg color */ 1880 case 32: case 33: case 34: 1881 case 35: case 36: case 37: 1882 scp->term.cur_attr = 1883 (scp->term.cur_attr & 0xF8FF) 1884 | (ansi_col[(n-30) & 7] << 8); 1885 break; 1886 case 40: case 41: /* set bg color */ 1887 case 42: case 43: case 44: 1888 case 45: case 46: case 47: 1889 scp->term.cur_attr = 1890 (scp->term.cur_attr & 0x8FFF) 1891 | (ansi_col[(n-40) & 7] << 12); 1892 break; 1893 } 1894 } 1895 break; 1896 1897 case 'x': 1898 if (scp->term.num_param == 0) 1899 n = 0; 1900 else 1901 n = scp->term.param[0]; 1902 switch (n) { 1903 case 0: /* reset attributes */ 1904 scp->term.cur_attr = scp->term.std_attr = 1905 current_default->std_attr; 1906 scp->term.rev_attr = current_default->rev_attr; 1907 break; 1908 case 1: /* set ansi background */ 1909 scp->term.cur_attr = scp->term.std_attr = 1910 (scp->term.std_attr & 0x0F00) | 1911 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1912 break; 1913 case 2: /* set ansi foreground */ 1914 scp->term.cur_attr = scp->term.std_attr = 1915 (scp->term.std_attr & 0xF000) | 1916 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1917 break; 1918 case 3: /* set ansi attribute directly */ 1919 scp->term.cur_attr = scp->term.std_attr = 1920 (scp->term.param[1]&0xFF)<<8; 1921 break; 1922 case 5: /* set ansi reverse video background */ 1923 scp->term.rev_attr = 1924 (scp->term.rev_attr & 0x0F00) | 1925 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1926 break; 1927 case 6: /* set ansi reverse video foreground */ 1928 scp->term.rev_attr = 1929 (scp->term.rev_attr & 0xF000) | 1930 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1931 break; 1932 case 7: /* set ansi reverse video directly */ 1933 scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8; 1934 break; 1935 } 1936 break; 1937 1938 case 'z': /* switch to (virtual) console n */ 1939 if (scp->term.num_param == 1) 1940 switch_scr(scp->term.param[0]); 1941 break; 1942 } 1943 } 1944 else if (scp->term.esc == 3) { 1945 if (c >= '0' && c <= '9') { 1946 if (scp->term.num_param < MAX_ESC_PAR) { 1947 if (scp->term.last_param != scp->term.num_param) { 1948 scp->term.last_param = scp->term.num_param; 1949 scp->term.param[scp->term.num_param] = 0; 1950 } 1951 else 1952 scp->term.param[scp->term.num_param] *= 10; 1953 scp->term.param[scp->term.num_param] += c - '0'; 1954 return; 1955 } 1956 } 1957 scp->term.num_param = scp->term.last_param + 1; 1958 switch (c) { 1959 1960 case ';': 1961 if (scp->term.num_param < MAX_ESC_PAR) 1962 return; 1963 break; 1964 1965 case 'A': /* set display border color */ 1966 if (scp->term.num_param == 1) 1967 scp->border=scp->term.param[0] & 0xff; 1968 if (scp == cur_console) 1969 set_border(scp->border); 1970 break; 1971 1972 case 'B': /* set bell pitch and duration */ 1973 if (scp->term.num_param == 2) { 1974 scp->bell_pitch = scp->term.param[0]; 1975 scp->bell_duration = scp->term.param[1]*10; 1976 } 1977 break; 1978 1979 case 'C': /* set cursor shape (start & end line) */ 1980 if (scp->term.num_param == 2) { 1981 scp->cursor_start = scp->term.param[0] & 0x1F; 1982 scp->cursor_end = scp->term.param[1] & 0x1F; 1983 if (scp == cur_console) 1984 cursor_shape(scp->cursor_start, 1985 scp->cursor_end); 1986 } 1987 break; 1988 1989 case 'F': /* set ansi foreground */ 1990 if (scp->term.num_param == 1) 1991 scp->term.cur_attr = scp->term.std_attr = 1992 (scp->term.std_attr & 0xF000) 1993 | ((scp->term.param[0] & 0x0F) << 8); 1994 break; 1995 1996 case 'G': /* set ansi background */ 1997 if (scp->term.num_param == 1) 1998 scp->term.cur_attr = scp->term.std_attr = 1999 (scp->term.std_attr & 0x0F00) 2000 | ((scp->term.param[0] & 0x0F) << 12); 2001 break; 2002 2003 case 'H': /* set ansi reverse video foreground */ 2004 if (scp->term.num_param == 1) 2005 scp->term.rev_attr = 2006 (scp->term.rev_attr & 0xF000) 2007 | ((scp->term.param[0] & 0x0F) << 8); 2008 break; 2009 2010 case 'I': /* set ansi reverse video background */ 2011 if (scp->term.num_param == 1) 2012 scp->term.rev_attr = 2013 (scp->term.rev_attr & 0x0F00) 2014 | ((scp->term.param[0] & 0x0F) << 12); 2015 break; 2016 } 2017 } 2018 scp->term.esc = 0; 2019} 2020 2021static void 2022ansi_put(scr_stat *scp, u_char c) 2023{ 2024 if (scp->status & UNKNOWN_MODE) 2025 return; 2026 2027 /* make screensaver happy */ 2028 if (scp == cur_console) { 2029 scrn_time_stamp = time.tv_sec; 2030 if (scrn_blanked) 2031 SCRN_SAVER(0); 2032 } 2033 in_putc++; 2034 if (scp->term.esc) 2035 scan_esc(scp, c); 2036 else switch(c) { 2037 case 0x1B: /* start escape sequence */ 2038 scp->term.esc = 1; 2039 scp->term.num_param = 0; 2040 break; 2041 case 0x07: 2042 if (scp == cur_console) 2043 sysbeep(scp->bell_pitch, scp->bell_duration); 2044 break; 2045 case '\t': /* non-destructive tab */ 2046 scp->crtat += (8 - scp->xpos % 8); 2047 scp->xpos += (8 - scp->xpos % 8); 2048 break; 2049 case '\b': /* non-destructive backspace */ 2050 if (scp->crtat > scp->crt_base) { 2051 scp->crtat--; 2052 if (scp->xpos > 0) 2053 scp->xpos--; 2054 else { 2055 scp->xpos += scp->xsize - 1; 2056 scp->ypos--; 2057 } 2058 } 2059 break; 2060 case '\r': /* return to pos 0 */ 2061 move_crsr(scp, 0, scp->ypos); 2062 break; 2063 case '\n': /* newline, same pos */ 2064 scp->crtat += scp->xsize; 2065 scp->ypos++; 2066 break; 2067 case '\f': /* form feed, clears screen */ 2068 clear_screen(scp); 2069 break; 2070 default: 2071 /* Print only printables */ 2072 *scp->crtat = (scp->term.cur_attr | scr_map[c]); 2073 scp->crtat++; 2074 if (++scp->xpos >= scp->xsize) { 2075 scp->xpos = 0; 2076 scp->ypos++; 2077 } 2078 break; 2079 } 2080 if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) { 2081 bcopy(scp->crt_base + scp->xsize, scp->crt_base, 2082 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2083 fillw(scp->term.cur_attr | scr_map[0x20], 2084 scp->crt_base + scp->xsize * (scp->ysize - 1), 2085 scp->xsize); 2086 scp->crtat -= scp->xsize; 2087 scp->ypos--; 2088 } 2089 in_putc--; 2090 if (delayed_next_scr) 2091 switch_scr(delayed_next_scr - 1); 2092} 2093 2094static void 2095scinit(void) 2096{ 2097 u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was; 2098 unsigned cursorat; 2099 int start = -1, end = -1, i; 2100 scr_stat *scp; 2101 2102 /* 2103 * catch that once in a blue moon occurence when scinit is called 2104 * TWICE, adding the CGA_BUF offset again -> poooff 2105 */ 2106 if (crtat != 0) 2107 return; 2108 /* 2109 * Crtat initialized to point to MONO buffer, if not present change 2110 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds 2111 * in the remapped offset at the "right" time 2112 */ 2113 was = *cp; 2114 *cp = (u_short) 0xA55A; 2115 if (*cp != 0xA55A) 2116 crtc_addr = MONO_BASE; 2117 else { 2118 *cp = was; 2119 crtc_addr = COLOR_BASE; 2120 Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short); 2121 } 2122 2123 /* Extract cursor location */ 2124 outb(crtc_addr,14); 2125 cursorat = inb(crtc_addr+1)<<8 ; 2126 outb(crtc_addr,15); 2127 cursorat |= inb(crtc_addr+1); 2128 crtat = Crtat + cursorat; 2129 2130 /* is this a VGA or higher ? */ 2131 outb(crtc_addr, 7); 2132 if (inb(crtc_addr) == 7) { 2133 u_long pa; 2134 u_long segoff; 2135 2136 crtc_vga = 1; 2137 2138 /* 2139 * Get the BIOS video mode pointer. 2140 */ 2141 segoff = *(u_long *)pa_to_va(0x4a8); 2142 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 2143 if (ISMAPPED(pa, sizeof(u_long))) { 2144 segoff = *(u_long *)pa_to_va(pa); 2145 pa = (((segoff & 0xffff0000) >> 12) 2146 + (segoff & 0xffff)); 2147 if (ISMAPPED(pa, 64)) 2148 video_mode_ptr = (char *)pa_to_va(pa); 2149 } 2150#if defined(FAT_CURSOR) 2151 start = 0; 2152 end = 18; 2153 cursor_shape(start, end); 2154#else 2155 get_cursor_shape(&start, &end); 2156#endif 2157 } 2158 current_default = &user_default; 2159 for (i = 0; i < NCONS; i++) { 2160 scp = &console[i]; 2161 scp->mode = M_VGA_C80x25; 2162 scp->term.esc = 0; 2163 scp->term.std_attr = current_default->std_attr; 2164 scp->term.rev_attr = current_default->rev_attr; 2165 scp->term.cur_attr = scp->term.std_attr; 2166 scp->border = BG_BLACK; 2167 scp->cursor_start = start; 2168 scp->cursor_end = end; 2169 scp->xsize = COL; 2170 scp->ysize = ROW; 2171 scp->bell_pitch = BELL_PITCH; 2172 scp->bell_duration = BELL_DURATION; 2173 scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 2174 scp->pid = 0; 2175 scp->proc = NULL; 2176 scp->smode.mode = VT_AUTO; 2177 if (i == 0) { 2178 scp->xpos = cursorat % COL; 2179 scp->ypos = cursorat / COL; 2180 scp->crt_base = Crtat; 2181 scp->crtat = crtat; 2182 } 2183 } 2184 kernel_console.esc = 0; 2185 kernel_console.std_attr = kernel_default.std_attr; 2186 kernel_console.rev_attr = kernel_default.rev_attr; 2187 kernel_console.cur_attr = kernel_default.std_attr; 2188 /* initialize mapscrn array to a one to one map */ 2189 for (i=0; i<sizeof(scr_map); i++) 2190 scr_map[i] = i; 2191} 2192 2193static void 2194scput(u_char c) 2195{ 2196 scr_stat *scp = &console[0]; 2197 term_stat save; 2198 2199 if (crtat == 0) 2200 scinit(); 2201 if( in_putc == 0) { 2202 ++in_putc; 2203 save = scp->term; 2204 scp->term = kernel_console; 2205 current_default = &kernel_default; 2206 ansi_put(scp, c); 2207 kernel_console = scp->term; 2208 current_default = &user_default; 2209 scp->term = save; 2210 --in_putc; 2211 } else { 2212 if( console_buffer_count < CONSOLE_BUFSIZE) 2213 console_buffer[console_buffer_count++] = c; 2214 } 2215} 2216 2217static u_char 2218*get_fstr(u_int c, u_int *len) 2219{ 2220 u_int i; 2221 2222 if (!(c & FKEY)) 2223 return(NULL); 2224 i = (c & 0xFF) - F_FN; 2225 if (i > n_fkey_tab) 2226 return(NULL); 2227 *len = fkey_tab[i].len; 2228 return(fkey_tab[i].str); 2229} 2230 2231static void 2232update_leds(int which) 2233{ 2234 int s; 2235 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 2236 2237 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 2238 if (key_map.n_keys > ALTGR_OFFSET) { 2239 if (which & ALKED) 2240 which |= CLKED; 2241 else 2242 which &= ~CLKED; 2243 } 2244 s = spltty(); 2245 kbd_cmd(KB_SETLEDS); 2246 kbd_cmd(xlate_leds[which & LED_MASK]); 2247 splx(s); 2248} 2249 2250/* 2251 * scgetc(noblock) - get character from keyboard. 2252 * If noblock = 0 wait until a key is pressed. 2253 * Else return NOKEY. 2254 */ 2255u_int 2256scgetc(int noblock) 2257{ 2258 u_char scancode, keycode; 2259 u_int state, action; 2260 struct key_t *key; 2261 static u_char esc_flag = 0, compose = 0; 2262 static u_int chr = 0; 2263 2264next_code: 2265 kbd_wait(); 2266 /* First see if there is something in the keyboard port */ 2267 if (inb(KB_STAT) & KB_BUF_FULL) 2268 scancode = inb(KB_DATA); 2269 else if (noblock) 2270 return(NOKEY); 2271 else 2272 goto next_code; 2273 2274 if (cur_console->status & KBD_RAW_MODE) 2275 return scancode; 2276#if ASYNCH 2277 if (scancode == KB_ACK || scancode == KB_RESEND) { 2278 kbd_reply = scancode; 2279 if (noblock) 2280 return(NOKEY); 2281 goto next_code; 2282 } 2283#endif 2284 keycode = scancode & 0x7F; 2285 switch (esc_flag) { 2286 case 0x00: /* normal scancode */ 2287 switch(scancode) { 2288 case 0xB8: /* left alt (compose key) */ 2289 if (compose) { 2290 compose = 0; 2291 if (chr > 255) { 2292 sysbeep(BELL_PITCH, BELL_DURATION); 2293 chr = 0; 2294 } 2295 } 2296 break; 2297 case 0x38: 2298 if (!compose) { 2299 compose = 1; 2300 chr = 0; 2301 } 2302 break; 2303 case 0xE0: 2304 case 0xE1: 2305 esc_flag = scancode; 2306 goto next_code; 2307 } 2308 break; 2309 case 0xE0: /* 0xE0 prefix */ 2310 esc_flag = 0; 2311 switch (keycode) { 2312 case 0x1C: /* right enter key */ 2313 keycode = 0x59; 2314 break; 2315 case 0x1D: /* right ctrl key */ 2316 keycode = 0x5A; 2317 break; 2318 case 0x35: /* keypad divide key */ 2319 keycode = 0x5B; 2320 break; 2321 case 0x37: /* print scrn key */ 2322 keycode = 0x5C; 2323 break; 2324 case 0x38: /* right alt key (alt gr) */ 2325 keycode = 0x5D; 2326 break; 2327 case 0x47: /* grey home key */ 2328 keycode = 0x5E; 2329 break; 2330 case 0x48: /* grey up arrow key */ 2331 keycode = 0x5F; 2332 break; 2333 case 0x49: /* grey page up key */ 2334 keycode = 0x60; 2335 break; 2336 case 0x4B: /* grey left arrow key */ 2337 keycode = 0x61; 2338 break; 2339 case 0x4D: /* grey right arrow key */ 2340 keycode = 0x62; 2341 break; 2342 case 0x4F: /* grey end key */ 2343 keycode = 0x63; 2344 break; 2345 case 0x50: /* grey down arrow key */ 2346 keycode = 0x64; 2347 break; 2348 case 0x51: /* grey page down key */ 2349 keycode = 0x65; 2350 break; 2351 case 0x52: /* grey insert key */ 2352 keycode = 0x66; 2353 break; 2354 case 0x53: /* grey delete key */ 2355 keycode = 0x67; 2356 break; 2357 2358 /* the following 3 are only used on the MS "Natural" keyboard */ 2359 case 0x5b: /* left Window key */ 2360 keycode = 0x69; 2361 break; 2362 case 0x5c: /* right Window key */ 2363 keycode = 0x6a; 2364 break; 2365 case 0x5d: /* menu key */ 2366 keycode = 0x6b; 2367 break; 2368 default: /* ignore everything else */ 2369 goto next_code; 2370 } 2371 break; 2372 case 0xE1: /* 0xE1 prefix */ 2373 esc_flag = 0; 2374 if (keycode == 0x1D) 2375 esc_flag = 0x1D; 2376 goto next_code; 2377 /* NOT REACHED */ 2378 case 0x1D: /* pause / break */ 2379 esc_flag = 0; 2380 if (keycode != 0x45) 2381 goto next_code; 2382 keycode = 0x68; 2383 break; 2384 } 2385 2386 if (compose) { 2387 switch (scancode) { 2388 /* key pressed process it */ 2389 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 2390 chr = (scancode - 0x40) + chr*10; 2391 goto next_code; 2392 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 2393 chr = (scancode - 0x47) + chr*10; 2394 goto next_code; 2395 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 2396 chr = (scancode - 0x4E) + chr*10; 2397 goto next_code; 2398 case 0x52: /* keypad 0 */ 2399 chr *= 10; 2400 goto next_code; 2401 2402 /* key release, no interest here */ 2403 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 2404 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 2405 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 2406 case 0xD2: /* keypad 0 */ 2407 goto next_code; 2408 2409 case 0x38: /* left alt key */ 2410 break; 2411 default: 2412 if (chr) { 2413 compose = chr = 0; 2414 sysbeep(BELL_PITCH, BELL_DURATION); 2415 goto next_code; 2416 } 2417 break; 2418 } 2419 } 2420 2421 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2422 if ((!agrs && (cur_console->status & ALKED)) 2423 || (agrs && !(cur_console->status & ALKED))) 2424 keycode += ALTGR_OFFSET; 2425 key = &key_map.key[keycode]; 2426 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2427 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2428 state ^= 1; 2429 2430 /* Check for make/break */ 2431 action = key->map[state]; 2432 if (scancode & 0x80) { /* key released */ 2433 if (key->spcl & 0x80) { 2434 switch (action) { 2435 case LSH: 2436 shfts &= ~1; 2437 break; 2438 case RSH: 2439 shfts &= ~2; 2440 break; 2441 case LCTR: 2442 ctls &= ~1; 2443 break; 2444 case RCTR: 2445 ctls &= ~2; 2446 break; 2447 case LALT: 2448 alts &= ~1; 2449 break; 2450 case RALT: 2451 alts &= ~2; 2452 break; 2453 case NLK: 2454 nlkcnt = 0; 2455 break; 2456 case CLK: 2457 clkcnt = 0; 2458 break; 2459 case SLK: 2460 slkcnt = 0; 2461 break; 2462 case ASH: 2463 agrs = 0; 2464 break; 2465 case ALK: 2466 alkcnt = 0; 2467 break; 2468 case META: 2469 metas = 0; 2470 break; 2471 } 2472 } 2473 if (chr && !compose) { 2474 action = chr; 2475 chr = 0; 2476 return(action); 2477 } 2478 } else { 2479 /* key pressed */ 2480 if (key->spcl & (0x80>>state)) { 2481 switch (action) { 2482 /* LOCKING KEYS */ 2483 case NLK: 2484 if (!nlkcnt) { 2485 nlkcnt++; 2486 if (cur_console->status & NLKED) 2487 cur_console->status &= ~NLKED; 2488 else 2489 cur_console->status |= NLKED; 2490 update_leds(cur_console->status); 2491 } 2492 break; 2493 case CLK: 2494 if (!clkcnt) { 2495 clkcnt++; 2496 if (cur_console->status & CLKED) 2497 cur_console->status &= ~CLKED; 2498 else 2499 cur_console->status |= CLKED; 2500 update_leds(cur_console->status); 2501 } 2502 break; 2503 case SLK: 2504 if (!slkcnt) { 2505 slkcnt++; 2506 if (cur_console->status & SLKED) { 2507 cur_console->status &= ~SLKED; 2508 pcstart(VIRTUAL_TTY(get_scr_num())); 2509 } 2510 else 2511 cur_console->status |= SLKED; 2512 update_leds(cur_console->status); 2513 } 2514 break; 2515 case ALK: 2516 if (!alkcnt) { 2517 alkcnt++; 2518 if (cur_console->status & ALKED) 2519 cur_console->status &= ~ALKED; 2520 else 2521 cur_console->status |= ALKED; 2522 update_leds(cur_console->status); 2523 } 2524 break; 2525 2526 /* NON-LOCKING KEYS */ 2527 case NOP: 2528 break; 2529 case RBT: 2530 shutdown_nice(); 2531 break; 2532 case SUSP: 2533 break; 2534 2535 case DBG: 2536#ifdef DDB /* try to switch to console 0 */ 2537 if (cur_console->smode.mode == VT_AUTO && 2538 console[0].smode.mode == VT_AUTO) 2539 switch_scr(0); 2540 Debugger("manual escape to debugger"); 2541 return(NOKEY); 2542#else 2543 printf("No debugger in kernel\n"); 2544#endif 2545 break; 2546 case LSH: 2547 shfts |= 1; 2548 break; 2549 case RSH: 2550 shfts |= 2; 2551 break; 2552 case LCTR: 2553 ctls |= 1; 2554 break; 2555 case RCTR: 2556 ctls |= 2; 2557 break; 2558 case LALT: 2559 alts |= 1; 2560 break; 2561 case RALT: 2562 alts |= 2; 2563 break; 2564 case ASH: 2565 agrs = 1; 2566 break; 2567 case META: 2568 metas = 1; 2569 break; 2570 case NEXT: 2571 switch_scr((get_scr_num()+1)%NCONS); 2572 break; 2573 case BTAB: 2574 action = F(16); 2575 default: 2576 if (action >= F_SCR && action <= L_SCR) { 2577 switch_scr(action - F_SCR); 2578 break; 2579 } 2580 if (action >= F_FN && action <= L_FN) 2581 action |= FKEY; 2582 return(action); 2583 } 2584 } 2585 else { 2586 if (metas) 2587 action |= MKEY; 2588 return(action); 2589 } 2590 } 2591 goto next_code; 2592} 2593 2594int 2595getchar(void) 2596{ 2597 u_char thechar; 2598 int s; 2599 2600 polling = 1; 2601 s = splhigh(); 2602 scput('>'); 2603 thechar = (u_char) scgetc(0); 2604 polling = 0; 2605 splx(s); 2606 switch (thechar) { 2607 default: 2608 if (thechar >= scr_map[0x20]) 2609 scput(thechar); 2610 return(thechar); 2611 case cr: 2612 case lf: 2613 scput(cr); scput(lf); 2614 return(lf); 2615 case bs: 2616 case del: 2617 scput(bs); scput(scr_map[0x20]); scput(bs); 2618 return(thechar); 2619 case cntld: 2620 scput('^'); scput('D'); scput('\r'); scput('\n'); 2621 return(0); 2622 } 2623} 2624 2625int 2626pcmmap(dev_t dev, int offset, int nprot) 2627{ 2628 if (offset > 0x20000) 2629 return EINVAL; 2630 return i386_btop((VIDEOMEM + offset)); 2631} 2632 2633static void 2634kbd_wait(void) 2635{ 2636 int i = 1000; 2637 2638 while (i--) { 2639 if ((inb(KB_STAT) & KB_READY) == 0) 2640 break; 2641 DELAY (10); 2642 } 2643} 2644 2645static void 2646kbd_cmd(u_char command) 2647{ 2648 int retry = 5; 2649 do { 2650 int i = 100000; 2651 2652 kbd_wait(); 2653#if ASYNCH 2654 kbd_reply = 0; 2655 outb(KB_DATA, command); 2656 while (i--) { 2657 if (kbd_reply == KB_ACK) 2658 return; 2659 if (kbd_reply == KB_RESEND) 2660 break; 2661 } 2662#else 2663 outb(KB_DATA, command); 2664 while (i--) { 2665 if (inb(KB_STAT) & KB_BUF_FULL) { 2666 int val; 2667 DELAY(10); 2668 val = inb(KB_DATA); 2669 if (val == KB_ACK) 2670 return; 2671 if (val == KB_RESEND) 2672 break; 2673 } 2674 } 2675#endif 2676 } while (retry--); 2677} 2678 2679static void 2680set_mode(scr_stat *scp) 2681{ 2682 char *modetable; 2683 char special_modetable[64]; 2684 int mode, font_size; 2685 2686 if (scp != cur_console) 2687 return; 2688 2689 /* mode change only on VGA's */ 2690 if (!crtc_vga || video_mode_ptr == NULL) { 2691 /* (re)activate cursor */ 2692 untimeout((timeout_t)cursor_pos, 0); 2693 cursor_pos(1); 2694 return; 2695 } 2696 2697 /* setup video hardware for the given mode */ 2698 switch (scp->mode) { 2699 case M_VGA_C80x50: 2700 bcopy(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 2701 special_modetable[2] = 8; 2702 special_modetable[19] = 7; 2703 modetable = special_modetable; 2704 goto setup_mode; 2705 2706 case M_VGA_M80x50: 2707 bcopy(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 2708 special_modetable[2] = 8; 2709 special_modetable[19] = 7; 2710 modetable = special_modetable; 2711 goto setup_mode; 2712 2713 case M_ENH_B80x43: 2714 bcopy(video_mode_ptr+(64*M_ENH_B80x25), &special_modetable, 64); 2715 special_modetable[2] = 8; 2716 special_modetable[19] = 7; 2717 special_modetable[28] = 87; 2718 modetable = special_modetable; 2719 goto setup_mode; 2720 2721 case M_ENH_C80x43: 2722 bcopy(video_mode_ptr+(64*M_ENH_C80x25), &special_modetable, 64); 2723 special_modetable[2] = 8; 2724 special_modetable[19] = 7; 2725 special_modetable[28] = 87; 2726 modetable = special_modetable; 2727 goto setup_mode; 2728 2729 case M_VGA_C40x25: case M_VGA_C80x25: /* VGA TEXT MODES */ 2730 case M_VGA_M80x25: 2731 case M_B40x25: case M_C40x25: 2732 case M_B80x25: case M_C80x25: 2733 case M_ENH_B40x25: case M_ENH_C40x25: 2734 case M_ENH_B80x25: case M_ENH_C80x25: 2735 2736 modetable = video_mode_ptr + (scp->mode * 64); 2737setup_mode: 2738 set_vgaregs(modetable); 2739 font_size = *(modetable + 2); 2740 /* change cursor type if set */ 2741 if (scp->cursor_start != -1 && scp->cursor_end != -1) 2742 cursor_shape( 2743 (scp->cursor_start >= font_size) 2744 ? font_size - 1 2745 : scp->cursor_start, 2746 (scp->cursor_end >= font_size) 2747 ? font_size - 1 2748 : scp->cursor_end); 2749 2750 /* set font type (size) */ 2751 switch (font_size) { 2752 case 0x08: 2753 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 2754 break; 2755 case 0x0E: 2756 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 2757 break; 2758 case 0x10: 2759 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 2760 break; 2761 default: 2762 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 2763 } 2764 2765 /* (re)activate cursor */ 2766 untimeout((timeout_t)cursor_pos, 0); 2767 cursor_pos(1); 2768 break; 2769 2770 case M_BG320: case M_CG320: case M_BG640: 2771 case M_CG320_D: case M_CG640_E: 2772 case M_CG640x350: case M_ENH_CG640: 2773 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 2774 2775 set_vgaregs(video_mode_ptr + (scp->mode * 64)); 2776 break; 2777 2778 default: 2779 /* call user defined function XXX */ 2780 break; 2781 } 2782 2783 /* set border color for this (virtual) console */ 2784 set_border(scp->border); 2785 return; 2786} 2787 2788static void 2789set_border(int color) 2790{ 2791 inb(crtc_addr+6); /* reset flip-flop */ 2792 outb(ATC, 0x11); outb(ATC, color); 2793 inb(crtc_addr+6); /* reset flip-flop */ 2794 outb(ATC, 0x20); /* enable Palette */ 2795} 2796 2797static void 2798set_vgaregs(char *modetable) 2799{ 2800 int i, s = splhigh(); 2801 2802 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 2803 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 2804 for (i=0; i<4; i++) { /* program sequencer */ 2805 outb(TSIDX, i+1); 2806 outb(TSREG, modetable[i+5]); 2807 } 2808 outb(MISC, modetable[9]); /* set dot-clock */ 2809 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 2810 outb(crtc_addr, 0x11); 2811 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 2812 for (i=0; i<25; i++) { /* program crtc */ 2813 outb(crtc_addr, i); 2814 outb(crtc_addr+1, modetable[i+10]); 2815 } 2816 inb(crtc_addr+6); /* reset flip-flop */ 2817 for (i=0; i<20; i++) { /* program attribute ctrl */ 2818 outb(ATC, i); 2819 outb(ATC, modetable[i+35]); 2820 } 2821 for (i=0; i<9; i++) { /* program graph data ctrl */ 2822 outb(GDCIDX, i); 2823 outb(GDCREG, modetable[i+55]); 2824 } 2825 inb(crtc_addr+6); /* reset flip-flop */ 2826 outb(ATC ,0x20); /* enable palette */ 2827 splx(s); 2828} 2829 2830static void 2831copy_font(int direction, int segment, int size, char* font) 2832{ 2833 int ch, line, s; 2834 u_char val; 2835 2836 outb(TSIDX, 0x01); val = inb(TSREG); /* blank screen */ 2837 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 2838 2839 /* setup vga for loading fonts (graphics plane mode) */ 2840 inb(crtc_addr+6); /* reset flip/flop */ 2841 outb(ATC, 0x30); outb(ATC, 0x01); 2842 outb(TSIDX, 0x02); outb(TSREG, 0x04); 2843 outb(TSIDX, 0x04); outb(TSREG, 0x06); 2844 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 2845 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 2846 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); /* addr = a0000, 64kb */ 2847 for (ch=0; ch < 256; ch++) 2848 for (line=0; line < size; line++) 2849 if (direction) 2850 *(char *)pa_to_va(VIDEOMEM+(segment*0x4000)+(ch*32)+line) = 2851 font[(ch*size)+line]; 2852 else 2853 font[(ch*size)+line] = 2854 *(char *)pa_to_va(VIDEOMEM+(segment*0x4000)+(ch*32)+line); 2855 /* setup vga for text mode again */ 2856 s = splhigh(); 2857 inb(crtc_addr+6); /* reset flip/flop */ 2858 outb(ATC, 0x30); outb(ATC, 0x0C); 2859 outb(TSIDX, 0x02); outb(TSREG, 0x03); 2860 outb(TSIDX, 0x04); outb(TSREG, 0x02); 2861 outb(GDCIDX, 0x04); outb(GDCREG, 0x00); 2862 outb(GDCIDX, 0x05); outb(GDCREG, 0x10); 2863 if (crtc_addr == MONO_BASE) { 2864 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */ 2865 } 2866 else { 2867 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */ 2868 } 2869 splx(s); 2870 outb(TSIDX, 0x01); val = inb(TSREG); /* unblank screen */ 2871 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 2872} 2873 2874static void 2875load_palette(void) 2876{ 2877 int i; 2878 2879 outb(PIXMASK, 0xFF); /* no pixelmask */ 2880 outb(PALWADR, 0x00); 2881 for (i=0x00; i<0x300; i++) 2882 outb(PALDATA, palette[i]); 2883 inb(crtc_addr+6); /* reset flip/flop */ 2884 outb(ATC, 0x20); /* enable palette */ 2885} 2886 2887static void 2888save_palette(void) 2889{ 2890 int i; 2891 2892 outb(PALRADR, 0x00); 2893 for (i=0x00; i<0x300; i++) 2894 palette[i] = inb(PALDATA); 2895 inb(crtc_addr+6); /* reset flip/flop */ 2896} 2897 2898#endif /* NSC */ 2899