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